由于想做一个收藏功能,于是想到了用数据库的方法去实现,顺其自然地我想到了以前看过的《第二行代码》中讲过这方面的知识,后来把书拿出来翻了翻,也去郭神的博客上看了看,收获还是不少滴。
关于LitePal的github地址在这里: https://github.com/LitePalFramework/LitePal
接下来就是怎么去用LitePal了。首先添加依赖:
dependencies {
compile 'org.litepal.android:core:1.6.0'
}
其次,在app/src/main目录下新建一个assets目录,然后在assets目录中新建一个litepal.xml文件,每次我创建这个文件的时候老跑到value里面去,只好把它拖回到assets中来。
然后就是litepal.xml的内容;
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="NewsCollectionStore"></dbname>
<version value="1"></version>
<list>
<mapping class="com.example.administrator.simpleapp.domain.LitePalNewsBean"></mapping>
</list>
</litepal>
dbname表示想要创建的数据库名字,version是数据库的版本,list中则表示具体的数据类啦。同时,也不能忘了配置LitePalApplication
<manifest>
<application
android:name="org.litepal.LitePalApplication"
...
>
...
</application>
</manifest>
还有一点需要注意的是,每个数据类需要继承DataSupport,比如我创建的这个数据库:
public class LitePalNewsBean extends DataSupport {
private int id;
private String content;
private String imageurl;
private String title;
private String weburl;
private String weburl2;
private String time;
...get...
...set...
}
上面的id不要忘记了,每在LitePal中添加一个数据,这个id就会自动增加的。
以上,LitePal就算配置完成了,现在只要进行任意一次数据库的操作,数据库就会创建出来。比如,我在MainActivity的Oncreate方法中添加:
LitePal.getDatabase();
剩下的,关于LitePal的增删改查就不说了,郭神的博客中有详细介绍。
由于我想实现的是给新闻增加收藏和删除的功能,所以主要考虑一下应该怎么去做。
接下来,创建一个LitePal的工具类,作用是
1、判断这条新闻是否已经被添加。
2、收藏一条新闻(添加数据到库)。
3、取消收藏一条新闻(从库中删数据)。
4、查找所有收藏的新闻(查找库中所有数据)
创建DataBaseUtils.class :
public class DataBaseUtils {
//查询某条新闻是否存在
public static boolean ifExitInCollect(String title) {
Boolean flag=false;
List<LitePalNewsBean> collectNews = DataSupport.select("title").where("title=?", title).find(LitePalNewsBean.class);
for (LitePalNewsBean collectNews1 : collectNews) {
if (collectNews1.getTitle() != null) {
//数据库中存在
flag=true;
}
}
return flag;
}
//查询所有新闻
public static List<LitePalNewsBean> getCollectNewsList(){
List<LitePalNewsBean> collectNewses = DataSupport.order("id desc").find(LitePalNewsBean.class);
return collectNewses;
}
//增加一条新闻
public static void addCollectNews(String content,String imageurl, String title,
String weburl, String weburl2, String time){
LitePalNewsBean collectNews=new LitePalNewsBean();
collectNews.setContent(content);
collectNews.setImageurl(imageurl);
collectNews.setTitle(title);
collectNews.setWeburl(weburl);
collectNews.setWeburl2(weburl2);
collectNews.setTime(time);
collectNews.save();
}
//删除当前新闻
public static void deleteCollectNews(String title){
DataSupport.deleteAll(LitePalNewsBean.class,"title=?",title);
}
}
接下来就来简单的实验一下,先做一个收藏功能的简陋雏形。
设置新闻列表ListView的长按监听:
private class MyOnItemLongClickListener implements AdapterView.OnItemLongClickListener{
private List<NewsTopBeanAuto.ResultBeanX.ResultBean.ListBean> listBeen;
public MyOnItemLongClickListener(List<NewsTopBeanAuto.ResultBeanX.ResultBean.ListBean> listBeen) {
this.listBeen = listBeen;
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
int realPosition = position - 1 + 4;
String title = listBeen.get(realPosition).getTitle();
boolean flag = DataBaseUtils.ifExitInCollect(title);
if (flag){
Toast.makeText(context, "已经收藏过了", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "收藏成功" , Toast.LENGTH_SHORT).show();
NewsTopBeanAuto.ResultBeanX.ResultBean.ListBean data = listBeen.get(realPosition);
DataBaseUtils.addCollectNews(data.getContent(), data.getPic(), data.getTitle(), data.getUrl(), data.getWeburl(), data.getTime());
}
// DataSupport.deleteAll(LitePalNewsBean.class);
List<LitePalNewsBean> allNews = DataSupport.findAll(LitePalNewsBean.class);
for (LitePalNewsBean theNews : allNews){
LogUtil.e("" + theNews.getTitle());
// LogUtil.e("" + theNews.getContent());
// LogUtil.e("" + theNews.getImageurl());
// LogUtil.e("" + theNews.getTime());
// LogUtil.e("" + theNews.getWeburl());
// LogUtil.e("" + theNews.getWeburl2());
LogUtil.e("" + theNews.getId());
}
return true;
}
}
由于上面的打印太多了,所以把其中一些注释掉,然后看一下效果吧:
同时看一下打印的日志:
上面两张图片的效果也算作是收藏功能的一个雏形吧。接下来就开始着手收藏功能的具体实现吧。
首先准备两张五角星图片,分别表示收藏的两种状态,res/menu中创建collection_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/my_collection"
android:title="收藏"
android:icon="@drawable/empty_star"
app:showAsAction="always"/>
</menu>
在Toolbar中去显示它,Toolbar怎么用就不谈了。
重要的是下面的两个方法中以及其中的逻辑:
...
private boolean flag;
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.collection_menu, menu);
MenuItem collectionItem = menu.getItem(0);
flag = DataBaseUtils.ifExitInCollect(title);
if (flag){ //数据存在,表示已经收藏过了
collectionItem.setIcon(R.drawable.full_star);
} else { //数据不存在,没有收藏
collectionItem.setIcon(R.drawable.empty_star);
}
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
case R.id.my_collection:
if (flag){ //如果现在处于收藏状态,点击则取消收藏,也就是删除收藏过的新闻
DataBaseUtils.deleteCollectNews(title);
flag = false;
item.setIcon(R.drawable.empty_star);
Toast.makeText(this, "取消收藏成功", Toast.LENGTH_SHORT).show();
for (LitePalNewsBean theNews : DataBaseUtils.getCollectNewsList()){
LogUtil.e("" + theNews.getTitle());
LogUtil.e("" + theNews.getId());
}
}else { //如果现在处于未收藏状态,点击则收藏,也就是添加这条没收藏过的新闻
DataBaseUtils.addCollectNews(content, imageUrl, title, webUrl, webUrl2, time);
flag = true;
item.setIcon(R.drawable.full_star);
Toast.makeText(this, "收藏成功", Toast.LENGTH_SHORT).show();
for (LitePalNewsBean theNews : DataBaseUtils.getCollectNewsList()){
LogUtil.e("" + theNews.getTitle());
LogUtil.e("" + theNews.getId());
}
}
break;
default:break;
}
return true;
}
核心的部分解决了,现在看一下效果:
搭配打印日志:
效果还是非常明显的,这样,收藏的功能就做好了,之后就是怎么把收藏的数据展示到界面上去了,前面这些都完成了,这个其实很简单的。就不详说了。
看一下收藏效果吧:
由于没有对数据库进行监听,所以取消收藏并且退出的时候,列表还没有刷新,这个问题以后再来解决。
接下来顺便做一下左滑退出活动的效果吧。
使用SwipeBackLayout这个控件去实现滑出活动的效果,github的地址是:
https://github.com/ikew0ng/SwipeBackLayout
参考的文章地址是:http://blog.csdn.net/eiuly/article/details/46472783
使用方法可以在上面这盘文章看到,下面是使用步骤:
1.关联库,我是下载的压缩包关联的库,导入library之后把gradle中一些版本数字改一下即可。
2.让想要使用该效果的活动继承SwipeBackActivity
3.获取SwipeBackLayout的实例:
private SwipeBackLayout swipeBackLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
swipeBackLayout = getSwipeBackLayout(); //获取实例
swipeBackLayout.setEdgeTrackingEnabled(SwipeBackLayout.EDGE_LEFT); //设置从左侧滑出活动
swipeBackLayout.setEdgeSize(DensityUtils.dip2px(NewsDetailActivity.this, 200)); //设置可以滑动的范围,这里使用的是像素转化工具类
//根据手机的分辨率从 dip 的单位 转成为 px(像素)
...
}
下面是工具类DensityUtils:
public class DensityUtils {
/**
* 根据手机的分辨率从 dip 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}
还有一些可加可不加的属性:
在使用的主题中添加下面的属性,否则滑动时activity的下层是黑色的
<item name="android:windowIsTranslucent">true</item>
当使用BaseActivity时,为了使首页不会滑动删除,只需如下设置即可
setSwipeBackEnable(false); //禁止滑动删除
最后看一下效果:
—————————————————————
更新
上面说过,由于没有给数据库添加监听,所以当取消收藏新闻的时候返回到收藏界面,这时候收藏列表是还来不及更新的。
之后试了很多办法还是没有解决,不过后来从一位高人那里得到真传,告知我可以使用广播去更新UI,我试了一下,确实可以!!!
接下来就说明一下是如何做到的。
自定义一个广播,并且要是动态注册的。
在CollectionActivity.class中(也就是收藏列表的界面)添加如下内容:
.
private IntentFilter filter;
private MyBroadCastReceiver myBroadCastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
myBroadCastReceiver = new MyBroadCastReceiver();
filter = new IntentFilter();
filter.addAction("com.example.administrator.simpleapp.MY_BROADCAST"); //自定义广播接收值
registerReceiver(myBroadCastReceiver, filter);
...
}
class MyBroadCastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
recyclerView.setAdapter(new MyCollectionRecyclerAdapter(CollectionActivity.this, DataBaseUtils.getCollectNewsList()));
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myBroadCastReceiver);
}
上面的代码中,addAction的广播值是自定义的。发送广播的时候也需要使用这个值。
还需要注意的是,动态注册的广播一定要及时取消注册,所以在活动的onDestroy中使用了unregisterReceiver方法。
接下来就是在NewsDetailActivity.class(新闻详情界面,就是带收藏键的)中去发送广播了,只需要给收藏按钮的点击事件中添加:
case R.id.my_collection:
if (flag){ //如果现在处于收藏状态,点击则取消收藏,也就是删除收藏过的新闻
DataBaseUtils.deleteCollectNews(title);
flag = false;
item.setIcon(R.drawable.empty_star);
Toast.makeText(this, "取消收藏成功", Toast.LENGTH_SHORT).show();
Intent intentFilter = new Intent();
intentFilter.setAction("com.example.administrator.simpleapp.MY_BROADCAST");
sendBroadcast(intentFilter);
}else { //如果现在处于未收藏状态,点击则收藏,也就是添加这条没收藏过的新闻
DataBaseUtils.addCollectNews(content, imageUrl, title, webUrl, webUrl2, time);
flag = true;
item.setIcon(R.drawable.full_star);
Toast.makeText(this, "收藏成功", Toast.LENGTH_SHORT).show();
Intent intentFilter = new Intent();
intentFilter.setAction("com.example.administrator.simpleapp.MY_BROADCAST");
sendBroadcast(intentFilter);
}
break;
default:break;
来看一下效果吧: