android 去重 比较两个list_【轻巧一刻】实战项目开发(二) list数据去重 数据追加与缓存...

【轻松一刻】实战项目开发(二) list数据去重 数据追加与缓存

引入开源控件 PullToRefresh 下拉刷新列表

每次下拉刷新都会发送请求,从接口返回json信息。

如果前后两次请求返回的数据中有重复的数据 该怎么给list去重

在上一篇中我们重写了实体Data的hashcode和equals方法

/*** 因为更新时间和unixtime都不是唯一的

* 这里使用唯一标识hashId来得到哈希码*/@Overridepublic inthashCode() {final int prime = 31;int result = 1;

result= prime * result + ((hashId == null) ? 0: hashId.hashCode());returnresult;

}/*** 因为更新时间和unixtime都不是唯一的

* 这里使用唯一标识hashId来比较*/@Overridepublic booleanequals(Object obj) {if (this ==obj)return true;if (obj == null)return false;if (getClass() !=obj.getClass())return false;

Data other=(Data) obj;if (hashId == null) {if (other.hashId != null)return false;

}else if (!hashId.equals(other.hashId))return false;return true;

}

因为data数据中只有hashId 是唯一标识,所以我们使用它做比较

使用set中不能添加重新元素的特性作为判断条件去重

/*** 重写Data中的hashCode和equals方法

* 使用set中不能添加重新元素的特性作为判断条件

* 将不重复的data元素依次放入临时的newlist

* 循环完毕后,将原始list清空,addAll(newlist)

*@paramlist

*@return

*/

public static List removeDuplicateDataInOrder(Listlist)

{

HashSet hashSet = new HashSet();

List newlist = new ArrayList();for (Iterator iterator =list.iterator(); iterator.hasNext();)

{

Data element=(Data) iterator.next();if(hashSet.add(element))

{

newlist.add(element);

}

}

list.clear();

list.addAll(newlist);returnlist;

}

而为了保证数据排列的先后顺序 我们应该在去重复之前做如下操作

1.如果是下拉刷新 在把数据添加到list的头部 list.addAll(0,list)

2.如果是上拉加载更多则把数据加载到尾部 list.addAll(list)

聚合数据接口 还可以按时间戳返回该时间点前或后的笑话列表

请求示例:http://japi.juhe.cn/joke/content/list.from?key=您申请的KEY&page=2&pagesize=10&sort=asc&time=1418745237

其中参数中的sort param sort desc:指定时间之前发布的,asc:指定时间之后发布的 ,time 表示时间戳

所以我们在上拉加载更多时 使用这种请求方式,以当前list中最后一条数据的时间戳为节点 返回该时间点前笑话列表。

故上拉加载更多时,list没有必要再去重复了、

if(flag ==PULL_DOWN_REFRESH_FLAG){//将新刷新的数据 添加到数据集头部

mCurrentListItems.addAll(0,result.getResult());//去除list中重复的数据

mCurrentListItems =UtilsHelper.removeDuplicateDataInOrder(mCurrentListItems);

}else if(flag ==PULL_UP_REFRESH_FLAG){//将新加载的数据 添加到数据集尾部//因为是以最后一条数据的时间戳向前查询,故不存在重复,无需list去重

mCurrentListItems.addAll(result.getResult());

pullUpPageNumber++;

}

如何得到本次请求之后更新了多少条数据呢,很简单只要保存上次的list,并与最新的list的size做对比即可。

使用handler处理,并在主线程更新UI

if(mLastListItems != null){int count = mCurrentListItems.size() -mLastListItems.size();android.os.Message msg= newandroid.os.Message();

msg.what=UPDATE_DATA_COUNT_MESSAGE;

msg.arg1=count;

mHandler.sendMessage(msg);

}

然后通知adapter数据集发生改变,并调用listview (listview是PullToRefreshListView的实例) 的onRefreshComplete()方法

//通知程序数据集已经改变,如果不做通知,那么将不会刷新mListItems的集合

mAdapter.notifyDataSetChanged();

mListView.onRefreshComplete();

假设我们处于没有网络的环境,那就有必要搞一个缓存了,以便离线查看,最好是缓存上次我们退出应用时显示的list数据。

没有使用sqlite,暂时使用文件,缓存到sdcard的一个目录中(/storage/emulated/0/qingsongyike/cache)

public static voidsaveJsonTextInLocalFile(String jsonData){boolean sdCardExist =Environment.getExternalStorageState()

.equals(android.os.Environment.MEDIA_MOUNTED);//判断sd卡是否存在

if(sdCardExist){

Log.d("UtilsHelper", "sdcard exist.");

File root=Environment.getExternalStorageDirectory();

String path= root.getPath()+File.separator+"qingsongyike"+File.separator+"cache";

Log.d("UtilsHelper", "dir path = "+path);

File file= newFile(path);if(!file.exists()){

file.mkdirs();

Log.d("UtilsHelper", "cache dir had create finished.");

}

File cacheFile= new File(path+File.separator+"cache.txt");if(!cacheFile.exists()){try{

cacheFile.createNewFile();

Log.d("UtilsHelper", "file path = "+path);

Log.d("UtilsHelper", "cache file is created.");

}catch(IOException e) {

e.printStackTrace();

}

}try{synchronized(obj) {

FileOutputStream fos= new FileOutputStream(cacheFile,false);

OutputStreamWriter writer= newOutputStreamWriter(fos);

writer.write(jsonData);

writer.flush();

writer.close();

fos.close();

}

Log.d("UtilsHelper", "cache data write finished.");//fos.write(JsonData.getBytes());//fos.flush();

} catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}

}else{

Log.d("UtilsHelper", "sdcard is not exist. Create cache file failed");

}

}

那我们需要将list数据重新组装成对象,并使用GSON的API函数将bean转换成json字符串

开一个子线程去做IO操作

class CacheThread implementsRunnable{

@Overridepublic voidrun() {//执行缓存操作 将刷新后最新的数据重组成对象 并转换成Json字符//不够50条 则都缓存//超过50条 则只缓存前50条//避免缓存文件较大 读取速度缓慢

String jsonData = null;

List list = new ArrayList();

list.addAll(mCurrentListItems);if(list.size() > 0 && list.size() < 50){

jsonData= UtilsHelper.beanConvertToJson(new Message(0, "Success", list));

}else if(list.size() >= 50){//将list中50条之后的都移除

Log.d("CacheThread", "list size is more than 50 !!");for (int i = list.size()-1; i >= 50; i--) {

list.remove(i);

}

Log.d("CacheThread", "list remove finish. size now is 50 !!");

jsonData= UtilsHelper.beanConvertToJson(new Message(0, "Success", list));

}else{

Log.d("CacheThread", "list size is 0 !!");

}//将Json字符保存到本地 以便没有网络时离线浏览

if(jsonData != null){

UtilsHelper.saveJsonTextInLocalFile(jsonData);

}else{

Log.d("CacheThread", "jsonData is null !!");

}

}

}

这里将只截取最多50条笑话信息,以避免数据量大造成的读写缓慢的问题。

其中将bean转换成json字符串的函数如下

//bean转换json

public staticString beanConvertToJson(Object obj){

Gson gson= newGson();

String json=gson.toJson(obj);

Log.d("UtilsHelper", "json = " +json);returnjson;

}

不要忘了在AndroidiManfest.xml中添加关于sdcard操作和文件读写的权限

只要有更新数据 我们就执行一次本地缓存的操作

打开文件 内容已经写进去了

未完待续。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值