Android搜索過濾

一、簡介

一般來說,我們可以使用以下幾種方式實現搜索:

1)暴力搜索——直接使用數據庫提供的功能,每次都從數據庫中讀取搜索的結果,存進一個數據結構用於Adapter顯示,調用notifyDataSetChanged()刷新數據;

2)利用filter進行搜索。這塊涉及到Filterable接口。推薦文章:Android實現Filterable通過輸入文本框實現聯繫人自動篩選。有兩點值得注意:a)Android原生組件AutoCompleteTextview就是使用該方法實現的;b)這個方法本質上還是調用notifyDataSetChanged()方法,並且還是要自己去實現搜索部分,只是整個方法看上去比較優雅,而且不用再去搜索數據庫,最重要的一點是這個時候搜索過程被自動移到另外一個線程之中,搜索完畢之後纔會刷新UI;

 二、Android做了哪些?
    1、爲了實現數據的過濾,andorid設計了抽象類Filter,進行異步和同步的數據過濾操作。
    2、在Adapter中繼承Filterable,提供給使用者Filter,進行過濾。
    3、在不同的View中,獲得查詢約束字符串,傳遞給Adapter,並且提供配合數據過濾的界面支持。
 三、Filter類
    Filter的使用流程如下:
    調用filter方法 ->在另一線程中調用performFiltering進行數據查詢->得到數據過濾結果後調用publishResults將結果返回到使用它的客戶端。
    該類中的performFiltering和publishResults均爲抽象方法,需要繼承者自己重寫。
比如我們可以自定義一個Filter類實現performFiltering和publishResults方法就可以實現過濾了。

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的具體實現

發佈了60 篇原創文章 · 獲贊 3 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章