Android9.0 Settings搜索实现原理分析

简介

Settings搜索是单独的一个模块,此文档主要讲解9.0上的原生搜索的功能,其源码位于android/packages/apps/SettingsIntelligence下,SettingsIntelligence是一个单独的应用

 

下面简单描述下搜索的主要业务流程:

1.Settings中点击搜索框,跳转至SettingsIntelligence中的搜索页面,即SearchActivity

而SearchActivity又切换到了SearchFragment.

2.SearchFragment中,SearchFeatureProviderImpl配合loaderManager,获取到数据库中的数据,然后返回给Adapter,并绑定到RecycleView中显示

3.在onBindViewHolder时通过onBind实现对应点击事件的跳转

数据获取

很疑惑,SettingsIntelligence中数据库的数据是怎么来的呢,是如何获取到的Settings中的相关页面的数据的呢?流程如下:

 

1.SearchFragment创建时进行了一些对象创建,如,也包括数据的初始化,如mSavedQueryController,SearchFeatureProviderImpl等等,mSearchFeatureProvider调用updateIndexAsync开启数据库的初始化

 

2.监听searchview输入框,通过restartLoaders调用loaderManager开启加载数据流程

 

 

 

3.load创建成功回调至onCreateLoader

 

4.mSearchFeatureProvider调用getSearchResultLoader方法,得到SearchResultLoader对象,SearchResultLoader在子线程中进行数据查找loadInBackground

 

 

5.loadInBackground时通过SearchResultAggregator的fetchResults进行数据查找以及过滤.并且创建了一个task集合,然后遍历的形式开启了task让其执行.之后将执行的结果返回到了taskResult结果集中

 

6.我们看看SearchFeatureProviderImpl中构建各类获取数据的task,包括DatabaseResultTask,InstalledAppResultTask,AccessibilityServiceResultTask等等.

且每个task都是继承自SearchQueryTask,而SearchQueryTask又是继承自FutureTask,因为FutureTask可以在线程运行结束后将结果返回.SearchQueryTask内封装了call方法的回调,调用抽象方法query完成数据的返回.

 

7.子类例如DatabaseResultTask,只需要实现方法query即可返回数据

 

8.可以看到,query中通过一系列查找的方法将数据添加到了resultSet结果集中,我们选取其中第一个firstWordQuery方法查看其实现,最终也是通过query方法调用

 

9.query中则拿到了Sqlite数据库的操作对IndexDatabaseHelper进行数据库操作,这个是一个单例对象,且内部定义了一些表和初始化的代码.

 

整体数据的获取流程结束了,但是问题还是没解决啊,数据库的数据是哪里来的.其实就在前面几步中,我们现在回头看第1步SearchFragment的onCreate方法中就包括mSearchFeatureProvider.updateIndexAsync,我们看看其内部实现

 

原来在这里,开启了一个异步任务进行了indexing的操作

 

 

 

 

其中实现如下,最重要的就是queryIntentContentProviders这个方法,通过包管理器拿到了ContentProvider,然后再通过ContentProvider查询对应进程内的数据,更新到了SettingsIntelligence的数据库中

 

其中PROVIDER_INTERFACE定义如下

 

我们可以搜索下Settings中是否有包含这个action,果然有声明一个内容提供者.

 

 

下面看看Settings中内容提供者是怎么提供的数据吧
 

数据提供

1.我们看看SettingsSearchIndexablesProvider的代码,发现只有几个query*相关的方法,而且是重写的,例如下图

那么肯定是父类做了一些操作,我们看看父类做了什么

 

2.SearchIndexablesProvider中做了一些封装和修改.对query方法进行了分类查询

 

 

 

 

 

 

 

其他诸如增删改的方法则直接通过抛异常和final修饰的方式屏蔽掉了

3.我们选取其中一个查询的方法看看

通过调用getSearchIndexableResourcesFromProvider获取到了一个SearchIndexableResource集合,并直接将数据保存到游标中了

 

 

 

 

 

 

 

 

4.而方法内部又是通过FeatureFactory.getFactory对象一步步调用,拿到了了一个class类型的集合values

 

5.查看代码可知values最终是从SearchIndexableResourcesImpl对象中获取到的

,SearchIndexableResourcesImpl比较简单,内部在对象构造方法调用时保存了数据到一个set集合,values就是这个集合,部分class类如下所示

 

6.在第四步中拿到values后,又通过遍历的方式,调用了DatabaseIndexingUtils.getSearchIndexProvider,这个方法也很简单,直接通过反射的方式去获取了对应class的一个字段 "SEARCH_INDEX_DATA_PROVIDER"

 

,class类型我们可知在第五步的时候添加了.我们选取集合中的WiFiSetting查看一下通过反射获取的这个字段是个什么值

 

7.可以很清楚的看到,SEARCH_INDEX_DATA_PROVIDER代表一个静态内部类的变量

,变量内返回的应该就是我们搜索的某个内容SearchIndexableRaw了.对应的内容提供者内的queryRawData方法返回的数据

 

 

 

 

 

 

 

总结

 

总结一下,搜索功能,其实就是对应需要提供被搜索的页面中,声明一个静态SearchIndexProvider对象,当内容提供者被外部调用查询方法的时候,会遍历一个集合类,通过反射的方式得到我们的这个SearchIndexProvider.在这个对象中,我们可以重写getXmlResourcesToIndex或者getRawDataToIndex的方式,提供对应的数据至内容提供者,将数据放在对应的Cursor中.

这样的话,SettingsIntelligence模块在搜索的时候获取到我们的ContentProvider,就可以通过query方法得到我们提供出来的数据了.

 

 

这里顺便总结一下Settings中增加/删除搜索内容的修改步骤:

1.增加/删除SearchIndexableResourcesImpl中集合类

2.在对应的集合类中添加SearchIndexProvider对象

3.通过重写对应的几个方法,增加/删除可被搜索的条目

文档下载链接

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值