Android Quick Search in Settings,androidquick
歡迎大家加入群裡交流:429664282
基於:android-6.0.1_r17 f4b8ad6
Android Settings中存在一個SearchIndexablesProvider,它提供了可供快速檢索的設定項。通過它,我們可以決定哪些系統設定可以被快速檢索,那些可以不被檢索。
SearchIndexablesProvider簡介
SearchIndexablesProvider是Android標準API,在SDK中可以找到,路徑是"android.provider.SearchIndexablesProvider"。它是一個虛基類,提供了一些抽象方法和常用方法。
抽象方法如下:
Cursor queryXmlResources(String[])
Cursor queryRawData(String[])
Cursor queryNonIndexableKeys(String[])
queryXmlResources方法返回一個Cursor,這個Cursor中包含了所有可以被索引的XmlResource,方法的參數是個String數組,用來表示傳入查詢的列。
queryRawData方法同queryRawData很類似,唯一區別是返回所有可以被索引的RawData。
queryNonIndexableKeys返回所有可以不被所有的NonIndexableKey。
檢索資料來源:SearchIndexableResources
在Settings中,所有可供檢索的資料資源,均被定義在SearchIndexableResources類中。
例如,Wifi設定頁面的所有可供檢索的資料,都通過WifiSettings.java提供。
1 static { 2 3 sResMap.put(WifiSettings.class.getName(), 4 5 new SearchIndexableResource( 6 7 Ranking.getRankForClassName(WifiSettings.class.getName()), 8 9 NO_DATA_RES_ID,10 11 WifiSettings.class.getName(),12 13 R.drawable.ic_settings_wireless));
特殊檢索資料:Indexable
在Settings中,提供了一類特殊的檢索資料,那就是實現了Indexable介面的類。
Indexable是定義在Settings內部的一種檢索資源,通過代碼的方式,返回可供檢索的資料,包括SearchIndexableResource和SearchIndexRaw。
所有實現了Indexable的類,必須提供一個public static的SEARCH_INDEX_DATA_PROVIDER變數,用來供Settings利用反射擷取到相應的檢索資料。
檢索資料提供者:SettingsSearchIndexablesProvider
在Settings中,SettingsSearchIndexablesProvider實現了SearchIndexablesProvider,並且提供了可供檢索的資料資源。這個資料資源以靜態map的方式定義在SearchIndexableResources中,並且在queryXmlResources方法中返回給資料要求者。
Settings並未提供任何的RawData和NonIndexableKey,所以它的queryRawData返回了一個空的Cursor。
更新檢索資料庫
在每次開啟Settings導航頁面的時候,Index.update()方法都會被調用,用來更新檢索資料。
Step1. 擷取所有SearchIndexablesProvider.
Step2. 添加可供檢索的資料到緩衝:addIndexablesFromRemoteProvider
對於每一個SearchIndexablesProvider,都需要進行這個操作。
Step2.1. 從XmlResource中添加檢索資料:addIndexablesForXmlResourceUri
所有定義在SearchIndexableResources中的檢索資料,均會在這一步中被添加進來。接下來,讓我們看看具體實現:
Step2.1.1 擷取檢索資料的Cursor
Step2.1.2 建立SearchIndexableResource,並加入到更新資料的緩衝列表:
Step2.2. 從RawData中添加檢索資料:addIndexablesForRawDataUri
Settings並未提供任何RawData,所以我們可以忽略這個步驟。
Step3. 添加不可供檢索的資料到緩衝
Settings並未提供任何NonIndexableKey,所以我們可以忽略這個步驟。
Step4. 更新緩衝的檢索資料
更新緩衝的檢索資料在updateInternal()方法中實現,下面我們來逐步分析下。
快取資料結構
到現在為止,Settings提供的檢索資料均被添加到"dataToUpdate"列表中。其他兩個未包含任何Settings提供的檢索資料。
Step4.1 建立一個UpdateIndexTask的背景工作來更新檢索資料庫
我們下面只關心dataToUpdate的相關操作。
Step4.2 更新dataToUpdate緩衝:processDataToUpdate
在這個方法中,我們對每一個SearchIndexableData都使用indexOneSearchIndexableData方進行更新。
Step4.3 對檢索資料進行索引:indexOneSearchIndexableData
這裡的檢索資料可以包括RawData和XmlResource,又或者Settings返回的SearchIndexableResource。
這裡為什麼是SearchIndexableResource?因為SettingsSearchIndexablesProvider把所有可以檢索的資料都已SearchIndexableResource插入到Cursor中,並且返回給資料查詢者,這裡也就是Settings本身。
Step4.4 對每一條檢索資料資源進行資料檢索:indexOneResource
前面我們提到過,Settings裡面有一種特殊的檢索資料資源:Indexable。
在這裡,如果我們發現這條檢索資料資源的xmlResId是NO_DATA_RES_ID,也就是說,當前這個檢索資料資源是一條特殊的檢索資料資源。我們就需要利用反射機製得到它的pusblic static的SEARCH_INDEX_DATA_PROVIDER。
Step4.4.1. 處理普通的檢索資料資源:xmlResId != NO_DATA_RES_ID
Step4.4.1.1. 從XML中解析檢索資料:indexFromResource
在這裡就到了整個實現流程的最末端了,解析整個PreferenceScreen的XMl檔案,並且把每一個合格項加入到檢索資料庫。
Step4.4.2. 處理特殊的檢索資料資源:Indexable
Step4.4.2.1. 從特殊的檢索資料來源擷取檢索資料:indexFromProvider
當拿到SEARCH_INDEX_DATA_PROVIDER變數後,我們得到它的兩個方法傳回值,根據傳回值的具體內容,我們將其更新到資料庫。