Step 22. SQLiteCursorDriver.query
这个函数定义在frameworks/base/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java文件中:
-
public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
-
......
-
-
public Cursor query(CursorFactory factory, String[] selectionArgs) {
-
// Compile the query
-
SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
-
-
try {
-
......
-
-
// Create the cursor
-
if (factory == null) {
-
mCursor = new SQLiteCursor(mDatabase, this, mEditTable, query);
-
} else {
-
mCursor = factory.newCursor(mDatabase, this, mEditTable, query);
-
}
-
-
......
-
return mCursor;
-
} finally {
-
......
-
}
-
}
-
-
......
-
}
这里我们就可以清楚地看到,这个函数首先会根据数据库对象mDatabase和原生SQL语句来构造一个SQLiteQuery对象,这个对象的创建的过程中,就会解析这个原生SQL语句,并且创建好数据库查询计划,这样做的好处是等到真正查询的时候就可以马上从数据库中获得取数据了,而不用去分析和理解这个SQL字符串语句,这个就是所谓的SQL语句编译了。有了这个SQLiteQuery对象之后,再把它和数据库对象mDatabase等待信息一起来创建一个SQLiteCursor对象,于是,这个SQLiteCursor对象就圈定要将来要从数据库中获取的数据了。这一步执行完成之后,就把这个SQLiteCursor对象返回给上层,最终回到Step 18中的Transport类bulkQuery函数中。有了这个SQLiteCursor对象之后,就通过创建一个CursorToBulkCursorAdaptor对象来把它和匿名共享内存关联起来,这样,就为将来从数据库中查询得到的数据找到了归宿。
CursorToBulkCursorAdaptor类定义在frameworks/base/core/java/android/database/CursorToBulkCursorAdaptor.java文件中,我们来看看它的对象的构造过程,即它的构造函数的实现:
-
public final class CursorToBulkCursorAdaptor extends BulkCursorNative
-
implements IBinder.DeathRecipient {
-
......
-
-
public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer, String providerName,
-
boolean allowWrite, CursorWindow window) {
-
try {
-
mCursor = (CrossProcessCursor) cursor;
-
if (mCursor instanceof AbstractWindowedCursor) {
-
AbstractWindowedCursor windowedCursor = (AbstractWindowedCursor) cursor;
-
......
-
-
windowedCursor.setWindow(window);
-
} else {
-
......
-
}
-
} catch (ClassCastException e) {
-
......
-
}
-
-
......
-
}
-
-
......
-
}
这里传进来的参数cursor的类型为SQLiteCursor,从上面的类图我们可以知道,SQLiteCursor实现了CrossProcessCursor接口,并且继承了AbstractWindowedCursor类,因此,上面第一个if语句的条件成立,于是就会把这个SQLiteCurosr对象转换为一个AbstractWindowedCursor对象,目的是为了调用它的setWindow函数来把传进来的CursorWindow对象window保存起来,以便后面用来保存数据。
Step 23. AbstractWindowedCursor.setWindow
这个函数定义在frameworks/base/core/java/android/database/AbstractWindowedCursor.java文件中:
-
public abstract class AbstractWindowedCursor extends AbstractCursor
-
{
-
......
-
-
public void setWindow(CursorWindow window) {
-
......
-
-
mWindow = window;
-
}
-
-
......
-
-
protected CursorWindow mWindow;
-
}
这个函数很简单,只是把参数window保存在AbstractWindowedCursor类的成员变量mWindow中。注意,这个成员变量mWindow的访问权限为protected,即AbstractWindowedCursor的子类可以直接访问这个成员变量。
这一步完成以后,就返回到前面的Step 14中去了,执行下面语句:
-
if (bulkCursor != null) {
-
reply.writeStrongBinder(bulkCursor.asBinder());
-
-
if (wantsCursorMetadata) {
-
reply.writeInt(bulkCursor.count());
-
reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(
-
bulkCursor.getColumnNames()));
-
}
-
} else {
-
......
-
}
这里的bulkCursor不为null,于是,就会把这个bulkCursor对象写入到数据流reply中,这个接口是要通过Binder进程间通信机制返回到第三方应用程序的,它的实际类型就是我们在前面Step 18中创建的CursorToBulkCursorAdaptor对象了。
从前面的Step 14的分析中,我们知道,这里的布尔变量wantsCursorMetadata为true,于是就会把请求数据的行数以及数据行的ID列索引号一起写入到数据流reply中去了。这里,我们重点分析IBulkCursor接口的count函数,因为这个调用使得这个Content Provider会真正去执行数据库查询的操作。至于是如何得到从数据库查询出来的数据行的ID列的位置呢?回忆前面这篇文章
Android应用程序组件Content Provider应用实例
,我们提到,如果我们想将数据库表中的某一列作为数据行的ID列的话,那么就必须把这个列的名称设置为"_id",这里的BulkCursorToCursorAdaptor类的静态成员函数findRowIdColumnIndex函数就是根据这个列名"_id"来找到它是位于数据行的第几列的。
CursorToBulkCursorAdaptor类定义在frameworks/base/core/java/android/database/CursorToBulkCursorAdaptor.java文件中,它的count成员函数的实现如下所示:
-
public final class CursorToBulkCursorAdaptor extends BulkCursorNative
-
implements IBinder.DeathRecipient {
-
......
-
-
public int count() {
-
return mCursor.getCount();
-
}
-
-
......
-
}
它的成员变量mCursor即为在前面Step 22中创建的SQLiteCursor对象,于是,下面就会执行SQLiteCursor类的getCount成员函数。
本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/967009,如需转载请自行联系原作者