android 源码角度全方位理解filter
2015-11-30 17:05
531 查看
写一个listview容易,写一个adapter容易,自己new一个线程过滤数据也容易,但是如何将过滤的效率发挥到最大化,不得不提一下android自带的filter类。
有同学肯定要问,过滤数据自己写一个完全没问题,为什么要用android自带的filter类?我原来也是自己写线程过滤,然而最近项目中遇到一个低配机,双核0.8GCPU,过滤效果实在是卡顿厉害,优化起见,使用了android内部filter试一下效果,结果真是比自己写的好用,于是认真学习了下源码,从头至尾备忘如下:
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
写篇帖子好难!
有同学肯定要问,过滤数据自己写一个完全没问题,为什么要用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
写篇帖子好难!
相关文章推荐
- 通知栏设置系统字体颜色
- android使用theme和style
- 关于Android service的一些基础知识集合
- Android兼容性问题 -- SparseArray.clone()方法异常
- Android自定义通知布局Notification,点击Notification导航切换回原Activity
- Android技巧分享——Android开发超好用工具吐血推荐(转)
- Selector标签
- Android Studio怎么删除项目
- Android Listview 第一页和最后一页会滑动问题
- 我的android错误集
- Android 线程Thread Runnable解析
- Android Activity进出动画
- Android 5.0.1(Lollipop)源码的下载、编译(eng版本)并烧录
- Android中dip、dp、sp、pt和px的区别
- Android开发总结笔记 Toasts(吐司泡) 1-1-17
- Android开源项目分类汇总
- android中的后退键——onBackPressed()的使用
- Android.mk -- 解析
- Adapter
- Android AsyncTask完全解析,带你从源码的角度彻底理解