您的位置:首页 > 移动开发 > Android开发

android 源码角度全方位理解filter

2015-11-30 17:05 531 查看
写一个listview容易,写一个adapter容易,自己new一个线程过滤数据也容易,但是如何将过滤的效率发挥到最大化,不得不提一下android自带的filter类。

有同学肯定要问,过滤数据自己写一个完全没问题,为什么要用android自带的filter类?我原来也是自己写线程过滤,然而最近项目中遇到一个低配机,双核0.8GCPU,过滤效果实在是卡顿厉害,优化起见,使用了android内部filter试一下效果,结果真是比自己写的好用,于是认真学习了下源码,从头至尾备忘如下:

private class RequestHandler extends Handler {
public RequestHandler(Looper looper) {
super(looper);
}

/**
* <p>Handles filtering requests by calling
* {@link Filter#performFiltering} and then sending a message
* with the results to the results handler.</p>
*
* @param msg the filtering request
*/
public void handleMessage(Message msg) {
int what = msg.what;
Message message;
switch (what) {
case FILTER_TOKEN:
RequestArguments args = (RequestArguments) msg.obj;
try {
args.results = performFiltering(args.constraint);
} catch (Exception e) {
args.results = new FilterResults();
Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
} finally {
message = mResultHandler.obtainMessage(what);
message.obj = args;
message.sendToTarget();
}

synchronized (mLock) {
if (mThreadHandler != null) {
Message finishMessage = mThreadHandler.obtainMessage(FINISH_TOKEN);
mThreadHandler.sendMessageDelayed(finishMessage, 3000);
}
}
break;
case FINISH_TOKEN:
synchronized (mLock) {
if (mThreadHandler != null) {
mThreadHandler.getLooper().quit();
mThreadHandler = null;
}
}
break;
}
}
}


View Code
其实除了filter方法,主要的高端逻辑都在这里,试想一个场景,如果我连续调用了五次filter,这5个msg的第1个已经被remove掉了,但是由它调用的performFiltering()耗时任务还在进行,2,3,4肯定排队过程中就被第5个msg干掉了,然后第1个msg过滤操作完成,给ResultsHandler发送消息更新UI,然后给RequestHandler发一个三秒延时消息,

接着执行msg5,这时候再调用一次filter,msg1和msg5就被干掉了,然后同样是执行完由msg5调用的performFiltering()再执行msg6,然后是msg5和msg6最终都生成一个延时消息,msg5生成的延时消息把mThreadHandler销毁了,msg6生成的延时消息到的时候,不做任何操作。

前面我们在filter()中看到过一次synchronized (mLock){},而在这个handler中有两个同步代码块,case FINISH_TOKEN中的同步代码块保证了,如果刚刚在filter中创建了mThreadHandler(这是UI线程的操作),会立刻移除所有之前的延迟消息,从而不会在此处去销毁掉mThreadHandler导致空指针异常。 case FILTER_TOKEN中的同步代码块的作用,目前还是想不出来到底有什么用,因为case FILTER_TOKEN和case FINISH_TOKEN本来就是队列执行,不存在争用锁的情况,所以不会存在线程间的时空差导致的空指针,有高手能看出作用还望不吝赐教。

好了,来总结一下吧,其实作者就是利用了looper中messageQueue排队队的特性,又有两处对象同步锁的妙用,保证了UI线程和HandlerThread不冲突,而过滤过程中的一些冗余msg都被新msg创建时候给干掉了,一个线程有序进行,大哉大牛!

PS,如果你对handler和looper的工作机制不太明白,可以先看下这个帖子:

http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html

写篇帖子好难!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: