1. 程式人生 > >Android O Settings原始碼流程分析(搜尋欄篇(中))

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搜尋框初始化搜尋索引完成;

 

點選進入下篇——搜尋及頁面跳轉