Setting学习(七)-搜索框(实现原理)

时间:2024-05-31 16:46:04

从上面已经知道搜索框布局的具体加载是在SearchFragment中进行的,下面就来看看SearchFragment的onCreate方法:
\packages\apps\settings\src\com\android\settings\search\SearchFragment.java
Setting学习(七)-搜索框(实现原理)
在onCreate方法中调用了SearchFeatureProvider的updateIndexAsync方法,它的具体实现是在SearchFeatureProviderImpl中实现的,在前面的onAttach方法中创建了mSearchFeatureProvider对象:
Setting学习(七)-搜索框(实现原理)
下面看看updateIndexAsync方法的具体内容:
==packages\apps\settings\src\com\android\settings\search\SearchFeatureProviderImpl.java ==
Setting学习(七)-搜索框(实现原理)
在updateIndexAsync中调用了getIndexingManager的indexDatabase方法,getIndexingManager返回的是mDatabaseIndexingManager对象:
Setting学习(七)-搜索框(实现原理)
就是说,最后调用的是DatabaseIndexingManager的indexDatabase方法
==packages\apps\settings\src\com\android\settings\search\DatabaseIndexingManager.java ==
Setting学习(七)-搜索框(实现原理)
在方法中启动了一个异步任务:
Setting学习(七)-搜索框(实现原理)
它在doInBackground中,相当于后台执行的方法是performIndexing
Setting学习(七)-搜索框(实现原理)
在performIndex中首先找到所有配置android.content.action.SEARCH_INDEXABLES_PROVIDER的provider:
\frameworks\base\core\java\android\provider\SearchIndexablesContract.java
Setting学习(七)-搜索框(实现原理)
addIndexablesFromRemoteProvider 添加要搜索的app的设置项

addNonIndexablesKeysFromRemoteProvider 添加不需要设置到快速搜索的设置项

updateDatabase 将数据更新到数据库之中

来看看addIndexablesFromRemoteProvider方法:
Setting学习(七)-搜索框(实现原理)
在上面的方法中,主要做了下面几件事:
1 .根据包名创建对应包的context对象
2 .根据authority创建指定的Uri
Setting学习(七)-搜索框(实现原理)
3 .通过context对象查找对应的Provider的数据
注意 :所有的要被列入搜索项的所在的APP的Provider都要继承SearchIndexablesProvider,而SearchIndexablesProvider继承ContentProvider
下面初始化要添加到数据库里的数据:
Setting学习(七)-搜索框(实现原理)
先获得指定包的ContentResolver,然后解析Cursor数据添加到mDataToProcess对象的dataToUpdate属性中:
Setting学习(七)-搜索框(实现原理)
dataToUpdate是一个list,“public List dataToUpdate”
数据加载完以后然后回到performIndexing,现在mDataToProcess中有数据,通过updateDatabase()方法把数据添加到快速搜索的数据库中
Setting学习(七)-搜索框(实现原理)
然后调用addDataToDatabase方法:
Setting学习(七)-搜索框(实现原理)
调用了indexOneSearchIndexableData方法:
Setting学习(七)-搜索框(实现原理)
indexOneSearchIndexableData中有两种方式添加到数据库中,接下来看看indexOneResource
Setting学习(七)-搜索框(实现原理)
可以看到如果sir.xmlResId > SearchIndexableResources.NO_DATA_RES_ID>如果为真,就是能够获取到搜索项的xml,就可以直接调用indexFromResource 方法进行解析xml,不然就调用indexFromProvider方法:
Setting学习(七)-搜索框(实现原理)
可以发现在这里面获取到要解析的xml文件后,也是调用indexFromResource来进行解析xml文件的,现在来看看indexFromResource的具体内容:
在indexFromResource解析布局:
Setting学习(七)-搜索框(实现原理)
解析完布局后调用updateOneRowWithFilteredData–> updateOneRow()方法添加到数据库
此方法最终将解析的数据更新至数据库
Setting学习(七)-搜索框(实现原理)
最后再回到performIndexing方法中,可以看到一个明显数据库相关的类IndexDatabaseHelper
Setting学习(七)-搜索框(实现原理)
这个数据明显和搜索索引相关的数据库,search_index.db 数据库的prefs_index表格中存放的就是搜索的设置选项。数据库路径
:/data/user_de/0/com.android.settings/databases/search_index.db
注意:该数据库的初始化不是在开机的时候进行的,在你第一次点进Settting搜索的时候回初始化一次,但是你再次点击进去不会再次初始化

如何添加或删除一个快速搜索

这涉及到了一个组装数据的类SearchIndexableResources.java
Setting学习(七)-搜索框(实现原理)
在添加一个快速搜索的时候有两种方式
一种是在新建SearchIndexableResource对象的时候,传入布局文件,如
DateTimeSettings.java
\packages\apps\settings\src\com\android\settings\DateTimeSettings.java
Setting学习(七)-搜索框(实现原理)
看到在创建SearchIndexableResource对象时候传入了R.xml.date_time_prefs文件
还有一种是“ NO_DATA_RES_ID”的,表示搜索匹配项里没有要解析的XML文件,在你添加好自己的写的设置项以后,需要在自己的文件里面创建SearchIndexProvider 的变量SEARCH_INDEX_DATA_PROVIDER,并继承BaseSearchIndexProvider内部类,然后重写getXmlResourcesToIndex,getNonIndexableKeys().等方法:
Setting学习(七)-搜索框(实现原理)
然后在SearchIndexableResources.java里面添加上面你写的文件:
Setting学习(七)-搜索框(实现原理)
第一个参数,类名;第二个参数,表示没有要加载的配饰文件;第三个参数,图标
要删除setting里面的快速搜索的话,在上面添加的两个方法,任意删除一个都可以,不过一般是在类的getNonIndexableKeys方法里面添加要移除的key
packages/apps/Settings/src/com/android/settings/accessibility/AccessibilitySettings.java
有时候仅仅移除这里还不够,因为有些快速搜索还被添加到了AccessibilitySettings.java类中,此时也需要在AccessibilitySettings.java类的getNonIndexableKeys()方法添加要移除的key

参考:https://blog.****.net/qq_34149526/article/details/83378184