listview优化问题
来源:互联网 发布:农村淘宝合伙人网站 编辑:程序博客网 时间:2024/06/03 15:15
Listview优化问题
一、 优化背景
后视镜项目中,需要设计一个视频回放的apk,spec定义如下。产品定义需求如下:
回放:点击文件名用设备自带播放器播放。
录像文件名:文件锁开关图标+存储时间+文件名组成。
录像文件锁:默认文件锁为打开状态(文件可被覆盖),如点击文件锁即文件锁图标变为锁止状态(文件无法被覆盖),再次点击文件锁图标为打开状态。
视频及照片文件删除或同步:长按文件2秒钟,弹出:“删除”、“同步至手机”按钮。
二、 设计方案
1 需求分析
根据需求,可以划分为以下几个部分:视频和图片分开加载显示,录像加锁功能,文件删除多选打开等文件操作。
2 设计方案
2.1 文件加载方式
通过ContentPrivider扫描sd卡所有图片和视频,在扫描前先将sd卡整个扫描一遍,不然的话可能刚刚添加的图片是不会查找出来的。
public void allScan(){
sendBroadcast(newIntent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"
+Environment.getExternalStorageDirectory())));
}
uri =MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
uri =MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
1
2
mCursor = contentResolver.query(uri, null, where, null,
null);
2.2 Listview显示
在实际优化中,有两种优化方式。
l 初始是采用直接继承BaseAdapter基类,public FileAdapter(ListView
mlistview,Context context,List<String> p),参数传进来是list<String>p,也就是说,在扫描出cursor之后,还需要将cursor的data属性传到list集合中,而adapter再对传进来的p进行处理。
进行优化处理——将cursor解析封装成一个一个对象集合,
public class RecordInfo {
privateString _dispalyName;
privateLong _size;
privateString _data;
privateString _tags;
privatelong _id;
privateboolean _checked;}
分装的好处是,由于在adapter进行操作数据集的时候,如果单独传进来的是一个路径,那么还需要将路径不断转化来转化去,系统性能较差。采用cursor先封装的好处是,有些数据已经有的东西,就可以直接拿出来用了,减少耗时操作,提高系统性能。
l 第二种方案是继承CursorAdapter。先来介绍下cursoradapter:
CursorAdapter是继承了BaseAdapter后覆盖它的getView方法,在该方法中调用了newView和bindView方法,我们在写CursorAdapter时必须实现它的这两个方法。
1) newView:并不是每次都会被调用的,它只在实例化的时候被调用,数据增加时也会调用,但是在重绘(比如修改条目中的TextView的内容)的时候不会被调用。
2) bindView:在绘制Item之前一定会调用bindView方法,它在重绘的时候也同样会被调用。
3) changeCursor:调用此方法后会把mCursor置为新传过来的cursor,把原来的cursor返回去并关掉。它的方法类似于adapter.notifyDataSetChanged()方法。
对比BaseAdapter和CursorAdapter:
CursorAdapter是继承于BaseAdapter的,是对BaseAdapter的进一步扩展。CursorAdapter适用于Cursor类型的数据集(从数据库读取的数据一般是这类型),而BaseAdapter是哪种类型的数据集都是适用的,包括Cursor,只不过对于Cursor,使用CursorAdapter比使用BaseAdapter要方便得多,因为很多的工作CursorAdapter都帮你做了。CursorAdapter还可以监听到数据的变化,实时更新数据。
1.
2.3 缩略图加载+异步操作+Loader
Android的加载器(loader)是从Android3.0开始出来的东西。要理解这里首先要先理解为什么会出现加载器呢?
如果没有加载器。。。。
首先Activity是我们的前端页面展现,数据库是我们的持久化地址,那么正常的逻辑就是在展示页面的渲染页面的阶段进行数据库查询。拿到数据以后才展示页面。但是这个逻辑有一些缺点:
首先是查询数据的逻辑放在了UI生成的同个线程中,这个就意味着在查询数据的时候,UI页面生成的工作被阻塞住了。UI一旦被阻塞用户就会被感知出来了,因此就会出现各种无相应页面(Application Not Response),或者activity页面延迟的现象,这对用户体验来说是不可接受的。
其次是在渲染页面的时候需要固定进行一次数据查询,但是这个是很不节省资源的。加入一个activity从一个停止状态回到前台,那么这个时候尽管数据并没有变化,但是也需要进行一次query操作。在浪费资源的同时也增加了页面渲染失败的风险。
还有就是当数据变化的时候如何通知页面进行修改呢?这个时候往往就要创建一个monitor角色,来当数据源变化的时候来让页面重新调用requery。
Loader做了两件时:1 在单独的线程中读取了数据;2 监视数据的更新。
2.4 Checkbox+listview
原先的baseadapter对checkbox的操作是创建一个集合存储这些checkbox的状态,但是在cursoradapter操作过程有些问题。Cursoradapter对于数据监听进行更新adapter,新加进来的数据的checkbox状态没有设置,所以会出现问题。对此的解决方案是,一检测到数据变动就直接进行赋值,但是这种方案不可行,如果数据是增加的,那么是可以接受的,但是如果是删除了数据变动,那么就麻烦了。我的修改方式是,在bindView里面检测是否有这个id的存在,没有就复制。
采用封装recordInfo的那种方式对checkbox的处理是,给recordInfo一个标志位,一开始全部赋予false,checkbox选中赋予true。删除只需要遍历为true的对象进行删除。
2.5 删除记录
class DeleteFileThread extends Thread {
public Handler mHandler;
private ArrayList<Long> mSrcFiles =null;
private int event = EVENT_DELETE_FILE_OK;
public void run() {
for (int i = 0; i <mSrcFiles.size(); i++) {
int result = getContentResolver().delete(uri,"_id=" + mSrcFiles.get(i), null);
if(result == 0)
event = EVENT_FAILED;
}
// Send response message to UI thread
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putInt("event", event);
msg.setData(b);
handler.sendMessage(msg);
}
public DeleteFileThread(ArrayList<Long>srcFiles) {
mSrcFiles= srcFiles;
}
}
采用cursoradapter的方式删除会自动更新数据库,采用recordInfo方式,注意要在recordInfos也要删除对象,不然会持有该对象无法更新listview。
- listview 优化问题
- listview优化问题
- ListView的优化问题
- ListView的优化问题
- listview优化问题
- 关于listview性能优化问题
- ListView性能优化问题总结
- ListView 优化注意的问题
- listView系列之优化问题
- ListView的优化问题详解
- Android中ListView的优化问题
- android内存溢出问题:ListView优化
- ListView优化以及checkbox状态问题
- Android关于ListView的优化问题
- ListView可能出现的问题及其优化
- ListView的优化问题以及策略
- 关于Android ListView的优化问题
- listView优化以及内存泄露问题
- HDU1159:Common Subsequence
- UDP-键盘录入方式数据
- Thinking in Java——第十六章-数组
- SQL中Group By的使用
- 阶段性学习的心得体会
- listview优化问题
- RMAN 备份
- HDU-1051 Wooden Sticks 【二维LIS(STL应用)+排序】
- JSP内置对象(一)
- 数据结构之队列的Java实现
- 1021. Deepest Root (25)
- TreeSet中自定义排序的两种方法
- HDU1513:Palindrome
- 关于UPnP Device Architecture 2.0的阅读笔记(六)