本节将分析ContentProvider中另一个比较复杂的知识点,即query的实现。从ContentResolver的query函数开始,其代码如下:
**ContentResolver.java::query**
~~~
/*
注意query中的参数,它们组合后得到的SQL语句如下(方括号中的语句为笔者添加的注释)
SELECT projection指定的列名[如果projection为null,则使用“*”]
FROM 表名[由目标CP根据uri参数设置] WHERE
(selection)[如果selection中有通配符,具体参数由selectionArgs指定]
ORDERYEDBY sortOrder
*/
public final Cursor query(Uri uri, String[]projection,
String selection, String[] selectionArgs, String sortOrder) {
/*
根据前面的分析,下面这个函数返回的provider的真实类型是ContentProviderProxy,
对应的Bn端对象的真实类型是ContentProvider的内部类Transport。本次执行query的
目标CP是MediaProvider
*/
IContentProvider provider = acquireProvider(uri);
//来看下面的代码
try {
long startTime = SystemClock.uptimeMillis();
//①调用远端进程的query函数
Cursor qCursor = provider.query(uri, projection,
selection, selectionArgs, sortOrder);
if (qCursor == null) {
//如果返回的结果为空,则释放provider,这个函数的作用在7.2.3节介绍过
releaseProvider(provider);
return null;
}
//②计算查询结果包含的数据项条数,结果保存在qCursor的内部变量中
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
//③最终返回给客户端一个游标对象,其真实数据类型为CursorWrapperInner
return new CursorWrapperInner(qCursor, provider);
}
~~~
上面这段代码揭示了ContentResolver query函数的工作流程:
- 调用远程CP的query函数,返回一个Cursor类型的对象qCursor。
- 该函数最终返给客户端的是一个CursorWrapperInner类型的对象。
Cursor和CursorWrappperInner这两个新出现的数据类型严重干扰了我们的思考。暂且不管它们,先来分析以上代码中列出的几个关键点函数。首先要分析的是第一个关键点函数query。