天天看點

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():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

         ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

SearchFeatureProviderImpl.java——>updateIndexAsync():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

getIndexingManager():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

DatabaseIndexingManager.java——>indexDatabase():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

可以看到在方法中開啟了一個線程任務IndexingTask:

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

它在背景所執行的方法 performIndexing():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

首先 查找系統中所有的配置了"android.content.action.SEARCH_INDEXABLES_PROVIDER"的Provider

添加其他APP的設定項 :addIndexablesFromRemoteProvider();

添加其他APP中不需要被搜尋到的設定項 :addNonIndexablesFromRemoteProvider();

上面的addIndexablesFromRemoteProvider會添加設定項到記憶體中的一個mDataToProcess對象裡,然後updateDate()将該對象更新到資料庫中

來看addIndexablesFromRemoteProvider()方法:

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
  • 根據目前包名建立對應包的context對象。
  • 根據目前包名建構指定URI,例如,
  • settings:content://com.android.settings/settings/indexables_xml_res
  • 然後通過context對象查找對應的Provider的資料
  • 所有的要被列入搜尋項的所在的APP的Provider都要繼承SearchIndexablesProvider
  • SearchIndexablesProvider繼承ContentProvider;
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

  ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

在該類中定義了查詢路徑并且實作通過比對不同Uri進行查找;

而在Settings中,則是由SettingsSearchIndexablesProvider實作相應查詢邏輯

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

在該類中采用Matrix建構虛拟的資料表,并通過SearchIndexableResource.values擷取到所有添加到map集合中的SearchIndexableResource;

回到addIndexablesFromRemoteProvider();

看一下方法addIndexablesForXmlResourceUri():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

首先擷取到指定包對應的ContentResolver,然後解析Cursor資料并且添加到UpdateData對象的dataToUpdate屬性中,該屬性是一個List集合;

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

回到performIndexing()繼續分析

然後執行方法updateDatabase():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

接着看方法addDataToDatabase():(加載資料到搜尋資料庫中)

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

看它裡面的重要方法indexOneSearchIndexableData():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

兩種添加到資料庫中的方法;

接着看方法indexOneResource():

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

                ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

                   …… 

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

            ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

indexFromResource() --> 使用XmlResourceParser解析xml布局

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

                ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

        ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

indexFromProvider() --> 擷取需要解析的布局,再次調用indexFromResource()方法;

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 
Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

         ……

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

updateOneRowWithFilteredData() --> updateOneRow() --> 此方法最終将解析的資料更新至資料庫

在此過程中涉及到了一個組裝資料的類SearchIndexableResources.java

例如将WiFi相關設定項加入到搜尋資料比對庫:

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

添加有兩種方式:

一種是直接在new SearchIndexableResource() 時傳入布局檔案;

另一種為"NO_DATA_RES_ID"表示此搜尋項比對沒有需要解析的xml檔案,此xml的解析在DatabaseIndexingManager.java中,

采用第二種時,需要在對應的類中建立一個SEARCH_INDEX_DATA_PROVIDER,類型為SearchIndexProvider,繼承BaseSearchIndexProvider并複寫其兩個方法: getXmlResourcesToIndex() 和 getNonIndexableKeys().

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

這些“WiFi”候選項被存入一個HashMap中 :

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

以候選項類名作為key,把每個候選項封裝成SearchIndexableResource對象作為value;

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

而SearchIndexableResource是繼承于SearchIndexableData:

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

而它是出現在addDataToDatabase()中循環周遊的對象,然後添加至資料庫中;

再次回到方法 performIndexing(),很顯然一個和資料庫相關的類:IndexDatabaseHelper.java:

Android O Settings源碼流程分析(搜尋欄篇(中))Android O Settings 

      ……

通過名字可以看出資料庫search_index.db是與搜尋索引相關的資料庫

資料庫路徑:/data/user_de/0/com.android.settings/databases/search_index.db

search_index.db 資料庫的prefs_index表格中存放的就是搜尋的設定選項

注:該資料庫的初始化不是在開機時,而是在每一次打開Settings或者切換使用者時進行。(系統為每一個使用者維護一個單獨的search_index)

至此,Settings搜尋框初始化搜尋索引完成;

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