SearchRecentSuggestionsProvider读写搜索历史代码分析

  SearchRecentSuggestionsProvider是用于实现简易搜索历史Provider的父类,官方API Guide在Adding Recent Query Suggestions一节介绍了添加搜索历史的方法,具体来说,除了必要的xml配置,只需实现自己的Provider继承SearchRecentSuggestionsProvider:

然后就可以使用SearchRecentSuggestions保存搜索历史:

  以上的流程简单易用,但如果希望独立控制搜索历史读写等功能,需要了解SearchRecentSuggestionsProvider对搜索历史的具体读写方法。

1. 向SearchRecentSuggestionsProvider写入搜索历史

  首先查看SearchRecentSuggestions的 saveRecentQuery() 方法:

saveRecentQuery() 新建线程调用了 saveRecentQueryBlocking() ,避免对ContentProvider的读写阻塞UI。 saveRecentQueryBlocking() 里就是具体的写入逻辑:

saveRecentQueryBlocking() 主要是常规的ContentProvider写入流程, mTwoLineDisplay 为使用双行搜索历史时添加一行额外的内容,几个Column名称定义如下:

mSuggestionsUri 内容为:

  至此,知道了Uri和各Column的定义,就可以按照saveRecentQueryBlocking()的方法,手动对搜索历史的ContentProvider进行插入操作。

2. SearchRecentSuggestionsProvider

2.1. 搜索历史的存储

  可以看到SearchRecentSuggestionsProvider使用SQLite数据库来存储搜索历史:

这里建立了一张名为 "suggestions" 的表,如果设置了 DATABASE_MODE_2LINES ,会额外添加 "display2" 字段。

2.2. SearchRecentSuggestionsProvider的insert()

  接下来关注SearchRecentSuggestionsProvider把上面的搜索历史写入存储的流程。SearchRecentSuggestionsProvider的 insert() 方法如下:

这里的逻辑非常简单,连UriMatcher都没用,只是比对了 sSuggestions ,然后就直接向数据库插入数据,其中 sSuggestions 为:

可见,前面SearchRecentSuggestions里面 mSuggestionsUri 中的 "/suggestions"  与这里的 sSuggestions 相匹配,所以SearchRecentSuggestions的 saveRecentQuery() 方法可以成功通过SearchRecentSuggestionsProvider保存搜索历史。另外 sSuggestions 的值也是2.1.中的表名,直接插入:

2.3.  SearchRecentSuggestionsProvider的query()

  接下来继续看SearchRecentSuggestionsProvider的query()方法,其逻辑根据请求Uri是否能够被UriMatcher匹配而分成两段,先看能够匹配的情况:

这里 mUriMatcher 只有一种匹配:

SearchManager.SUGGEST_URI_PATH_QUERY 为:

query() 中,如果请求Uri成功匹配 URI_MATCH_SUGGEST ,则向 sSuggestions 表查询包含 selectionArgs[0] 的所有条目。

  对于请求Uri不能被 mUriMatcher 匹配的情况,会从Uri提取表名,并向该表发起查询,具体流程可以查看源码。

3. 从SearchRecentSuggestionsProvider读取搜索历史

  通过上面的分析,可以得到从SearchRecentSuggestionsProvider读取搜索历史的方法: