Android源码阅读-Filter过滤器
Filter
顺便看看,Android中过滤器是怎么实现的?
注释中提到,Filter一般通过继承Filterable实现
具体实现
这是SimpleAdapter出现的一个过滤首字母item的一个过滤器
private class SimpleFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mUnfilteredData == null) {
mUnfilteredData = new ArrayList<Map<String, ?>>(mData);
}
if (prefix == null || prefix.length() == 0) {
ArrayList<Map<String, ?>> list = mUnfilteredData;
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;
int count = unfilteredValues.size();
ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);
for (int i = 0; i < count; i++) {
Map<String, ?> h = unfilteredValues.get(i);
if (h != null) {
int len = mTo.length;
for (int j = 0; j < len; j++) {
String str = (String) h.get(mFrom[j]);
String[] words = str.split(" ");
int wordCount = words.length;
for (int k = 0; k < wordCount; k++) {
String word = words[k];
if (word.toLowerCase().startsWith(prefixString)) {
newValues.add(h);
break;
}
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
mData = (List<Map<String, ?>>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
通过performFiltering处理Result和publishResults返回数据进行刷新。
Filter抽象类源码
抽象类Filter中filter开启了对于数据的异步过滤操作。
寻找一下调用,发现AbsListView和AutoCompleteTextView 都有调用:
Abs中:
// 判断类型
if (mAdapter instanceof Filterable) {
Filter f = ((Filterable) mAdapter).getFilter();
// Filter should not be null when we reach this part
if (f != null) {
f.filter(s, this);
} else {
throw new IllegalStateException("You cannot call onTextChanged with a non "
+ "filterable adapter");
}
}
Auto中:
protected void performFiltering(CharSequence text, int keyCode) {
mFilter.filter(text, this);
}
filter的调用通过一个限制词和接口,接口判断完成百分比。
filter:
public final void filter(CharSequence constraint, FilterListener listener) {
// 锁
synchronized (mLock) {
if (mThreadHandler == null) {
// 开一个线程进行 这个线程自带Looper
HandlerThread thread = new HandlerThread(
THREAD_NAME, android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mThreadHandler = new RequestHandler(thread.getLooper());
}
final long delay = (mDelayer == null) ? 0 : mDelayer.getPostingDelay(constraint);
// 回收池拿一个msg
Message message = mThreadHandler.obtainMessage(FILTER_TOKEN);
// 包含了过滤的一切信息的对象
RequestArguments args = new RequestArguments();
// make sure we use an immutable copy of the constraint, so that
// it doesn't change while the filter operation is in progress
args.constraint = constraint != null ? constraint.toString() : null;
args.listener = listener;
message.obj = args;
// 移除了之前未处理的消息
mThreadHandler.removeMessages(FILTER_TOKEN);
mThreadHandler.removeMessages(FINISH_TOKEN);
mThreadHandler.sendMessageDelayed(message, delay);
}
}
处理request的handler:
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;
}
}
}
处理结果的Handler:
private class ResultsHandler extends Handler {
/**
* <p>Messages received from the request handler are processed in the
* UI thread. The processing involves calling
* {@link Filter#publishResults(CharSequence,
* android.widget.Filter.FilterResults)}
* to post the results back in the UI and then notifying the listener,
* if any.</p>
*
* @param msg the filtering results
*/
@Override
public void handleMessage(Message msg) {
RequestArguments args = (RequestArguments) msg.obj;
// 返回数据
publishResults(args.constraint, args.results);
if (args.listener != null) {
int count = args.results != null ? args.results.count : -1;
args.listener.onFilterComplete(count);
}
}
}
Android源码阅读-Filter过滤器的更多相关文章
- SpringMVC源码阅读:过滤器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- Android源码阅读 – Zygote
@Dlive 本文档: 使用的Android源码版本为:Android-4.4.3_r1 kitkat (源码下载: http://source.android.com/source/index.ht ...
- Android拓展系列(11)--打造Windows下便携的Android源码阅读环境
因为EXT和NTFS格式的差异,我一直对于windows下阅读Android源码感到不满. 前几天,想把最新的android5.0的源码下下来研究一下,而平时日常使用的又是windows环境,于是专门 ...
- tomcat源码阅读之过滤器
一.Servlet过滤器: 1.介绍: Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用. Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request ...
- Android源码阅读技巧--查找开发者选项中显示触摸操作源码
在开发者模式下,在开发者选项中,可以勾选“显示触摸操作”,然后只要点击屏幕就会在点击的位置有圈圈显示.如何找到绘制圈圈的代码部分,有什么技巧来阅读代码量这么大的android系统源码呢?以下请跟着小老 ...
- Android 源码阅读之SMS,MMS
主界面: com.android.mms.ui.ConversationList.java [extends ListActivity] 点击新建信息:onListItemClick -〉 posi ...
- Android源码阅读笔记二 消息处理机制
消息处理机制: .MessageQueue: 用来描述消息队列2.Looper:用来创建消息队列3.Handler:用来发送消息队列 初始化: .通过Looper.prepare()创建一个Loope ...
- Android 源码阅读笔记
Zygote: .Zygote 是系统启动之后创建的第二个进程2.Zygote 创建zygote Socket.虚拟机3.Zygote 在虚拟机中通过forkSystemServer, 创建Serve ...
- 【安卓本卓】Android系统源码篇之(一)源码获取、源码目录结构及源码阅读工具简介
前言 古人常说,“熟读唐诗三百首,不会作诗也会吟”,说明了大量阅读诗歌名篇对学习作诗有非常大的帮助.做开发也一样,Android源码是全世界最优秀的Android工程师编写的代码,也是A ...
随机推荐
- [Q&A] 应用程序清单生成失败
当在 Silverlight 客户端属性里(如下图),添加"允许在浏览器外运行应用程序"和"在浏览器内运行时需要提升的信任"时, 图1 目录下会自动生成如下两个 ...
- 学习笔记之-------UIScrollView 基本用法 代理使用
//contentSize.contentInset和contentOffset 是 scrollView三个基本的属性. // 滚动 self.ScrollView.contentSize =sel ...
- 为什么volatile不能保证原子性而Atomic可以?
在上篇<非阻塞同步算法与CAS(Compare and Swap)无锁算法>中讲到在Java中long赋值不是原子操作,因为先写32位,再写后32位,分两步操作,而AtomicLong赋值 ...
- Oracle学习总结_day05_集合_连接查询
本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day05_集合_连接查询 集合操作符 UNION ( ...
- springmvc的类型转换
一.springmvc的类型转换 (一)默认情况下,springmvc内置的类型转换器只能 将"yyyy/MM/dd"类型的字符串转换为Date类型的日期 情境一: 而现在我们无 ...
- Linux(四)__javaee开发环境的搭建
一.VMware tools 通过VMware tools来实现主机和VM共享文件,详细介绍 记得重启就能实现本机和虚拟机之间复制粘贴文件. 二.搭建java环境: 一般linux都会预装openjd ...
- thinkcmf 常用操作
11-16 thinkcmf 核心文件结构:simplewind--model--lite--model.class.php /controller.class.php Mobile---contr ...
- browserify学习总结
前言 在未接触browserify,虽然我知道它是一个前端构建工具,但还是有几个疑问: 1. browserify出现的日期? 2. 能构建哪些文件? 3. 附加的browserify代码体积是多大? ...
- 轻松掌握:JavaScript代理模式、中介者模式
代理模式.中介者模式 代理模式 在面向对象设计中,有一个单一职责原则,指就一个类(对象.函数)而言,应该仅有一个引起它变化的原因.如果一个对象承担了过多的职责,就意味着它将变得巨大,引起它变化的原因就 ...
- DevExpress TreeList使用心得
来自:http://www.cnblogs.com/sndnnlfhvk/archive/2011/05/15/2046920.html 最近做项目新增光纤线路清查功能模块,思路和算法已经想好了,些代 ...