一般來說,我們可以使用以下幾種方式實現搜索:
1)暴力搜索——直接使用數據庫提供的功能,每次都從數據庫中讀取搜索的結果,存進一個數據結構用於Adapter顯示,調用notifyDataSetChanged()刷新數據;
2)利用filter進行搜索。這塊涉及到Filterable接口。推薦文章:Android實現Filterable通過輸入文本框實現聯繫人自動篩選。有兩點值得注意:a)Android原生組件AutoCompleteTextview就是使用該方法實現的;b)這個方法本質上還是調用notifyDataSetChanged()方法,並且還是要自己去實現搜索部分,只是整個方法看上去比較優雅,而且不用再去搜索數據庫,最重要的一點是這個時候搜索過程被自動移到另外一個線程之中,搜索完畢之後纔會刷新UI;
CursorFilter類就是Filter類的繼承。CursorFilter在performFiltering中並沒有直接進行數據的過濾,而是加入了CursorFilterClient成員,將過濾的操作轉讓給了CursorFilterClient,實際上CursorAdpater就是繼承了CursorFilterClient接口,也就是說過濾操作實際上是在CursorAdapter中執行的。
CursorAdapter實現Filterable接口實現了下面的方法
public
Filter getFilter() {
if (mCursorFilter == null) {
mCursorFilter = new CursorFilter(this);
}
return mCursorFilter;
}
看一下CursorFilter的實現,實現Filter的兩個抽象方法
class
CursorFilter extends Filter {
CursorFilterClient mClient;
CursorFilter(CursorFilterClient client) {
mClient = client;
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Cursor cursor = mClient.runQueryOnBackgroundThread(constraint);
FilterResults results = new FilterResults();
if (cursor != null) {
results.count = cursor.getCount();
results.values = cursor;
} else {
results.count = 0;
results.values = null;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Cursor oldCursor = mClient.getCursor();
if (results.values != null && results.values != oldCursor) {
mClient.changeCursor((Cursor) results.values);
}
}
查詢工作交給了CursorFilterClient這個類,而CursorAdapter實現了這個接口,所以
Cursor cursor = mClient.runQueryOnBackgroundThread(constraint);
這個方法是在CursorAdapter中實現的,我們看下
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (mFilterQueryProvider != null) {
return mFilterQueryProvider.runQuery(constraint);
}
return mCursor;
}
其中的mFilterQueryProvider需要我設置一下
public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
mFilterQueryProvider = filterQueryProvider;
}
看一下FilterQueryProvider這個接口,只有一個抽象方法
public
interface FilterQueryProvider {
Cursor runQuery(CharSequence constraint);
}
所以我們需要在外面繼承這個接口實現它,並且實現runQuery方法中的查詢搜索。
然後通過CursorAdapter的setFilterQueryProvider方法設置,之後整個機制完全串聯起來,在外調用adapter.getFilter().filter(et_filter.getText().toString()); 即可啓動整個過濾機制。
整個機制實際上是用異步查詢然後顯示的流程,主要的流程處理在Filter的類中。下篇文章分析下Filter的具體實現