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搜尋框初始化搜尋索引完成;
點選進入下篇——搜尋及頁面跳轉