天天看点

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

点击进入下篇——搜索及页面跳转