这段时间,工作转到应用程序开发上来,很多观念都有些转变。以前总觉得使用别人的库不如自己写的好用,现在才知道原来是因为自己了解的太少,没有用好。
言归正传,Android为ListView提供了Filter对象,对显示的条目进行过滤。最常见的用法就是Contact中,根据在输入框中输入姓名的字母显示过滤。当然android系统中默认提供的过滤功能非常有限,不支持号码或是其他信息过滤。我曾见过有人为了支持对号码的过滤,就将Android提供的那套机制屏蔽掉,每当过滤事件发生时,手动起AsyncQueryHander去异步查询。当查询完毕时调用CursorAdapter.changeCursor更新Cursor。虽然基本上做法没错,流程上也跟Android实现过滤的机制大体相同,但重复了制造轮子的过程,而原有的轮子,只需稍加修改足以满足新的需求。
我们只需要重写public Cursor runQueryOnBackgroundThread(CharSequence constraint),或者实现接口FilterQueryProvider的对象,再将该对象setFilterQueryProvider给CursorAdapter即可。
下面分析下CursorAdapter与Filter的实现框架。
先说下Filter:
Filter与AsyncQueryHander实现基本类似,它包含两个Hander:RequestHandler和ResultHandler,以及一个HandlerThread:名为Filter的线程。RequestHandler与Filter线程绑定,过滤请求都是通过RequestHandler发送给Filter线程。当过滤产生后,通过mResultHandler将数据push给UI显示。
CursorFilter继承Filter,它提供了CursorFilterClient接口,CursorAdapter实现CursorFilterClient接口。CursorFilter会在过滤的某些点回调CursorFilterClient接口的对应函数,我们就是通过这些被回调的函数,改变Filter的行为,以实现自己的目的。这与我们熟知的Activity生命周期上的:onCreate->onResume->onPause......的做法类似。
来看下这个重要的接口CursorFilterClient的定义
interface CursorFilterClient {
CharSequence convertToString(Cursor cursor);
Cursor runQueryOnBackgroundThread(CharSequence constraint);
Cursor getCursor();
void changeCursor(Cursor cursor);
}
runQueryOnBackgroundThread是运行在Filter线程中,返回的Cursor将传给ResultHandler,最后传给UI显示。所以上面的例子中,我们要添加对号码的查询,只需在这里自己组织下查询条件,包含对号码的查询,找数据库查询下,将查询结果返回即可。
changeCursor在ResultHandler向UI送结果时被调用,通过它更新显示过滤后的数据。我们可以重载它,在过滤数据显示前,做点需要的事情(比如更新下SectionIndexer)。
getCursor只是返回下Adapter中保存的Cursor,convertToString在CursorAdapter没有被用到,不管它了。