上面是ContentProvider和IContentProvider的关系
先总结一下:
1.ContentResolver#query()->IContentProvider#query()->ContentProvider#query()->SQLiteDatabase#query()->return a SQLiteCursor.
2.上面返回的SQLiteCursor中还未创建CursorWindow。只是有一个与SQLiteDatabase的Connection和SQLiteQuery,即可以从数据库中获取指定数据。但是需要执行SQLiteCursor#fillWindow()会创建CursorWindow并申请共享内存,然后把查询到的数据放到CursorWindow所代表的共享内存中。
3.从onTransact写入到reply的是BulkCursorDescriptor(包含了CursorToBulkCursorAdapter和CursorWindow)
4.IContentProvider#query()返回的是CursorToBulkCursorAdapter,将CursorToBulkCursorAdapter和CursorWindow封装起来,CursorToBulkCursorAdapter extends AbstractWindowedCursor。
5.ContentResolver#query()返回的是ContentProviderClient#CursorWrapperInner。其中CursorWrapperInner封装了CursorToBulkCursorAdapter,CursorWrapperInner只做了一点点简单的事。
6.SQLiteCursor并没有返回给Bp端,实际只返回了CursorWindow和IBulkCursor(CursorToBulkCursorAdapter),CursorToBulkCursorAdapter组合了SQLite,所以IBulkCursor允许Client访问服务端的SQLiteCursor。然后Bp端收到CursorWindow和IBulkCursor后,把这两个成员封装到BulkCursorToCursorAdapter以便给客户使用,因为客户只认识Cursor接口。在一般情况下,client只需通过CursorWindow便可以获取到想要的数据,而不用与SQLiteCursor通信。只有在以下条件下才需要与SQLiteCursor通信:
CursorToBulkCursorAdapter#onMove
if (mWindow == null
|| newPosition < mWindow.getStartPosition()
|| newPosition >= mWindow.getStartPosition() + mWindow.getNumRows()) {
setWindow(mBulkCursor.getWindow(newPosition));
}
上面代码可以看出,当position超出Window中的数据范围时,需要重新fillWindow。因为Window中不一定包含了所有查询到的数据,因为window只申请了2M的空间,不一定所有数据都能装下。
定义空间大小:
sCursorWindowSize = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_cursorWindowSize) * 1024;//window的大小就是这么大,config_cursorWindowSize为2048
看ContentResolver的query方法:
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
return null;
}
IContentProvider stableProvider = null;
Cursor qCursor = null;
try {
long startTime = SystemClock.uptimeMillis();
ICancellationSignal remoteCancellationSignal = null;
if (cancellationSignal != null) {
cancellationSignal.throwIfCanceled();
remoteCancellationSignal = unstableProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
try {
//无论是unstable还是stable,都是调用ContentProvider的Bp端query方法,后面可以知道,qCursor是BulkCursorToCursorAdapter类型
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
// reference though, so we might recover!!! Let's try!!!!
// This is exciting!!1!!1!!!!1
unstableProviderDied(unstableProvider);
stableProvider = acquireProvider(uri);
if (stableProvider == null) {
return null;
}
qCursor = stableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
}
if (qCursor == null) {
return null;
}
// Force query execution. Might fail and throw a runtime exception here.
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
// Wrap the cursor object into CursorWrapperInner object.
final IContentProvider provider = (stableProvider != null) ? stableProvider
: acquireProvider(uri);
final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);//从ContentResolver返回的是一个CursorWrapperInner
stableProvider = null;
qCursor = null;
return wrapper;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
return null;
} finally {
if (qCursor != null) {
qCursor.close();
}
if (cancellationSignal != null) {
cancellationSignal.setRemote(null);
}
if (unstableProvider != null) {
releaseUnstableProvider(unstableProvider);
}
if (stableProvider != null) {
releaseProvider(stableProvider);
}
}
}
从ContentProviderProxy#query()入手:
public Cursor query(String callingPkg, Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
throws RemoteException {
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();//注意这个类型的对象
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);//写入binder标志
data.writeString(callingPkg);//写入方法的参数
url.writeToParcel(data, 0);
int length = 0;
if (projection != null) {
length = projection.length;
}
data.writeInt(length);
for (int i = 0; i < length; i++) {
data.writeString(projection[i]);
}
data.writeString(selection);
if (selectionArgs != null) {
length = selectionArgs.length;
} else {
length = 0;
}
data.writeInt(length);
for (int i = 0; i < length; i++) {
data.writeString(selectionArgs[i]);//写参数
}
data.writeString(sortOrder);//写参数
data.writeStrongBinder(adaptor.getObserver().asBinder());//传递一个ContentObserver,一个Binder对象
data.writeStrongBinder(cancellationSignal != null ? cancellationSignal.asBinder() : null);
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);//向Bn端发起请求
DatabaseUtils.readExceptionFromParcel(reply);//读取返回值
if (reply.readInt() != 0) {
//所有参数都包含在了BuklCursorDescriptor中,包括IBulkCursor和CursorWindow,后面会分析这个createFromParcel(),
BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);//读取一个序列化对象,并反序列化该对象
adaptor.initialize(d);//把BuildCursorDescriptor和adaptor绑定,最后返回这个Cursor,所以从ContentProvider的Bp端返回的是BulkCursorToCursorAdapter
} else {
adaptor.close();
adaptor = null;
}
return adaptor;
} catch (RemoteException ex) {
adaptor.close();
throw ex;
} catch (RuntimeException ex) {
adaptor.close();
throw ex;
} finally {
data.recycle();
reply.recycle();
}
}
主要向ContentProvider的Bn端发送了一个ContentObserver的Bp端,还有进行查询的SQL语句信息
分析BulkCursorDescriptor.CREATOR.createFromParcel(reply):
public final class BulkCursorDescriptor implements Parcelable {
public static final Parcelable.Creator<BulkCursorDescriptor> CREATOR =
new Parcelable.Creator<BulkCursorDescriptor>() {
@Override
public BulkCursorDescriptor createFromParcel(Parcel in) {
BulkCursorDescriptor d = new Bul