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搜索框初始化搜索索引完成;
点击进入下篇——搜索及页面跳转