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过滤器的更多相关文章

  1. SpringMVC源码阅读:过滤器

    1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...

  2. Android源码阅读 – Zygote

    @Dlive 本文档: 使用的Android源码版本为:Android-4.4.3_r1 kitkat (源码下载: http://source.android.com/source/index.ht ...

  3. Android拓展系列(11)--打造Windows下便携的Android源码阅读环境

    因为EXT和NTFS格式的差异,我一直对于windows下阅读Android源码感到不满. 前几天,想把最新的android5.0的源码下下来研究一下,而平时日常使用的又是windows环境,于是专门 ...

  4. tomcat源码阅读之过滤器

    一.Servlet过滤器: 1.介绍: Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用. Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request ...

  5. Android源码阅读技巧--查找开发者选项中显示触摸操作源码

    在开发者模式下,在开发者选项中,可以勾选“显示触摸操作”,然后只要点击屏幕就会在点击的位置有圈圈显示.如何找到绘制圈圈的代码部分,有什么技巧来阅读代码量这么大的android系统源码呢?以下请跟着小老 ...

  6. Android 源码阅读之SMS,MMS

    主界面: com.android.mms.ui.ConversationList.java  [extends ListActivity] 点击新建信息:onListItemClick -〉 posi ...

  7. Android源码阅读笔记二 消息处理机制

    消息处理机制: .MessageQueue: 用来描述消息队列2.Looper:用来创建消息队列3.Handler:用来发送消息队列 初始化: .通过Looper.prepare()创建一个Loope ...

  8. Android 源码阅读笔记

    Zygote: .Zygote 是系统启动之后创建的第二个进程2.Zygote 创建zygote Socket.虚拟机3.Zygote 在虚拟机中通过forkSystemServer, 创建Serve ...

  9. 【安卓本卓】Android系统源码篇之(一)源码获取、源码目录结构及源码阅读工具简介

    前言        古人常说,“熟读唐诗三百首,不会作诗也会吟”,说明了大量阅读诗歌名篇对学习作诗有非常大的帮助.做开发也一样,Android源码是全世界最优秀的Android工程师编写的代码,也是A ...

随机推荐

  1. [Q&A] 应用程序清单生成失败

    当在 Silverlight 客户端属性里(如下图),添加"允许在浏览器外运行应用程序"和"在浏览器内运行时需要提升的信任"时, 图1 目录下会自动生成如下两个 ...

  2. 学习笔记之-------UIScrollView 基本用法 代理使用

    //contentSize.contentInset和contentOffset 是 scrollView三个基本的属性. // 滚动 self.ScrollView.contentSize =sel ...

  3. 为什么volatile不能保证原子性而Atomic可以?

    在上篇<非阻塞同步算法与CAS(Compare and Swap)无锁算法>中讲到在Java中long赋值不是原子操作,因为先写32位,再写后32位,分两步操作,而AtomicLong赋值 ...

  4. Oracle学习总结_day05_集合_连接查询

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day05_集合_连接查询 集合操作符 UNION ( ...

  5. springmvc的类型转换

     一.springmvc的类型转换 (一)默认情况下,springmvc内置的类型转换器只能 将"yyyy/MM/dd"类型的字符串转换为Date类型的日期 情境一: 而现在我们无 ...

  6. Linux(四)__javaee开发环境的搭建

    一.VMware tools 通过VMware tools来实现主机和VM共享文件,详细介绍 记得重启就能实现本机和虚拟机之间复制粘贴文件. 二.搭建java环境: 一般linux都会预装openjd ...

  7. thinkcmf 常用操作

    11-16  thinkcmf 核心文件结构:simplewind--model--lite--model.class.php /controller.class.php Mobile---contr ...

  8. browserify学习总结

    前言 在未接触browserify,虽然我知道它是一个前端构建工具,但还是有几个疑问: 1. browserify出现的日期? 2. 能构建哪些文件? 3. 附加的browserify代码体积是多大? ...

  9. 轻松掌握:JavaScript代理模式、中介者模式

    代理模式.中介者模式 代理模式 在面向对象设计中,有一个单一职责原则,指就一个类(对象.函数)而言,应该仅有一个引起它变化的原因.如果一个对象承担了过多的职责,就意味着它将变得巨大,引起它变化的原因就 ...

  10. DevExpress TreeList使用心得

    来自:http://www.cnblogs.com/sndnnlfhvk/archive/2011/05/15/2046920.html 最近做项目新增光纤线路清查功能模块,思路和算法已经想好了,些代 ...