Android O Settings原始碼流程分析(搜尋欄篇(中))
Android O Settings
Settings 搜尋欄
中篇——實現原理
初始化候選項:
相關類:
/packages/apps/Settings/src/com/android/settings/SettingsActivity.java
/packages/apps/Settings/src/com/android/settings/search/SearchActivity.java
/packages/apps/Settings/src/com/android/settings/search/SearchFragment.java
/packages/apps/Settings/src/com/android/settings/search/SearchFeatureProviderImpl.java
/packages/apps/Settings/src/com/android/settings/search/DatabaseIndexingManager.java
/packages/apps/Settings/src/com/android/settings/search/IndexDatabaseHelper.java
/packages/apps/Settings/src/com/android/settings/search/SearchIndexableResources.java
/frameworks/base/core/java/android/provider/SearchIndexableResource.java
/packages/apps/Settings/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
/frameworks/base/core/java/android/provider/SearchIndexablesProvider.java
首先來分析系統設定可以對哪些設定項進行構建搜尋資料庫,並且是如何載入的;
SearchFragment.java——>onCreate():
……
SearchFeatureProviderImpl.java——>updateIndexAsync():
getIndexingManager():
DatabaseIndexingManager.java——>indexDatabase():
可以看到在方法中開啟了一個執行緒任務IndexingTask:
它在後臺所執行的方法 performIndexing():
首先 查詢系統中所有的配置了"android.content.action.SEARCH_INDEXABLES_PROVIDER"的Provider
新增其他APP的設定項 :addIndexablesFromRemoteProvider();
新增其他APP中不需要被搜尋到的設定項 :addNonIndexablesFromRemoteProvider();
上面的addIndexablesFromRemoteProvider會新增設定項到記憶體中的一個mDataToProcess物件裡,然後updateDate()將該物件更新到資料庫中
來看addIndexablesFromRemoteProvider()方法:
- 根據當前包名建立對應包的context物件。
- 根據當前包名構建指定URI,例如,
- settings:content://com.android.settings/settings/indexables_xml_res
- 然後通過context物件查詢對應的Provider的資料
- 所有的要被列入搜尋項的所在的APP的Provider都要繼承SearchIndexablesProvider
- SearchIndexablesProvider繼承ContentProvider;
……
在該類中定義了查詢路徑並且實現通過匹配不同Uri進行查詢;
而在Settings中,則是由SettingsSearchIndexablesProvider實現相應查詢邏輯
在該類中採用Matrix構建虛擬的資料表,並通過SearchIndexableResource.values獲取到所有新增到map集合中的SearchIndexableResource;
回到addIndexablesFromRemoteProvider();
看一下方法addIndexablesForXmlResourceUri():
首先獲取到指定包對應的ContentResolver,然後解析Cursor資料並且新增到UpdateData物件的dataToUpdate屬性中,該屬性是一個List集合;
回到performIndexing()繼續分析
然後執行方法updateDatabase():
接著看方法addDataToDatabase():(載入資料到搜尋資料庫中)
看它裡面的重要方法indexOneSearchIndexableData():
兩種新增到資料庫中的方法;
接著看方法indexOneResource():
……
……
……
indexFromResource() --> 使用XmlResourceParser解析xml佈局
……
……
indexFromProvider() --> 獲取需要解析的佈局,再次呼叫indexFromResource()方法;
……
updateOneRowWithFilteredData() --> updateOneRow() --> 此方法最終將解析的資料更新至資料庫
在此過程中涉及到了一個組裝資料的類SearchIndexableResources.java
例如將WiFi相關設定項加入到搜尋資料匹配庫:
新增有兩種方式:
一種是直接在new SearchIndexableResource() 時傳入佈局檔案;
另一種為"NO_DATA_RES_ID"表示此搜尋項匹配沒有需要解析的xml檔案,此xml的解析在DatabaseIndexingManager.java中,
採用第二種時,需要在對應的類中建立一個SEARCH_INDEX_DATA_PROVIDER,型別為SearchIndexProvider,繼承BaseSearchIndexProvider並複寫其兩個方法: getXmlResourcesToIndex() 和 getNonIndexableKeys().
這些“WiFi”候選項被存入一個HashMap中 :
以候選項類名作為key,把每個候選項封裝成SearchIndexableResource物件作為value;
而SearchIndexableResource是繼承於SearchIndexableData:
而它是出現在addDataToDatabase()中迴圈遍歷的物件,然後新增至資料庫中;
再次回到方法 performIndexing(),很顯然一個和資料庫相關的類:IndexDatabaseHelper.java:
……
通過名字可以看出資料庫search_index.db是與搜尋索引相關的資料庫
資料庫路徑:/data/user_de/0/com.android.settings/databases/search_index.db
search_index.db 資料庫的prefs_index表格中存放的就是搜尋的設定選項
注:該資料庫的初始化不是在開機時,而是在每一次開啟Settings或者切換使用者時進行。(系統為每一個使用者維護一個單獨的search_index)
至此,Settings搜尋框初始化搜尋索引完成;