其中,CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);详细解释请看博客或者书。
如图:第四步
~/Android/frameworks/base/core/java/android/content
----ContentProvider.java
public abstract class ContentProvider implements ComponentCallbacks {
......
class Transport extends ContentProviderNative {
......
public IBulkCursor bulkQuery(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
IContentObserver observer, CursorWindow window) {
......
Cursor cursor = ContentProvider.this.query(uri, projection,
selection, selectionArgs, sortOrder);
......
return new CursorToBulkCursorAdaptor(cursor, observer,
ContentProvider.this.getClass().getName(),
hasWritePermission(uri), window);
}
......
}
......
}
主要做了以下几件事:
(1)调用AriticlesProvider的query方法,获取了SQLiteCursor对象。
(2)由cursor和window对象,形成CursorToBulkCursorAdaptor对象。
如图,第五步
if (bulkCursor != null) {
reply.writeStrongBinder(bulkCursor.asBinder());
if (wantsCursorMetadata) {
reply.writeInt(bulkCursor.count());
reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(
bulkCursor.getColumnNames()));
}
}
传递CursorToBulkCursorAdaptor对象,如下图:
如图:第六步,省略binder_transaction传输过程,因为上面已经分析过了。
如图:第七步
~/Android/frameworks/base/core/java/android/content
----ContentProviderNative.java
IBulkCursor bulkCursor = null;
IBinder bulkCursorBinder = reply.readStrongBinder();
if (bulkCursorBinder != null) {
bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
if (wantsCursorMetadata) {
int rowCount = reply.readInt();
int idColumnPosition = reply.readInt();
if (bulkCursor != null) {
adaptor.set(bulkCursor, rowCount, idColumnPosition);
}
}
}
bulkCursor为BulkCursorProxy对象如下:
adaptor.set(bulkCursor, rowCount, idColumnPosition);
把BulkCursorProxy对象放入到BulkCursorToCursorAdaptor对象的句柄变量mBulkCursor中。
如图:第八步
return new CursorWrapperInner(qCursor, provider);
最后返回了这个对象,qCursor是BulkCursorToCursorAdaptor对象,provider为ContentProviderProxy对象。
至此,我们形成了下图:
进程间通信结束了,下面我们分析如何应用匿名共享内存来传输数据。
在前面的一篇文章Android Content Provider的启动过程源代码分析http://blog.csdn.net/jltxgcy/article/details/37725749,最后获取了ContentProviderProxy对象,通过进程间通信来传递数据。
public class ArticlesAdapter {
......
private ContentResolver resolver = null;
public ArticlesAdapter(Context context) {
resolver = context.getContentResolver();
}
......
public Article getArticleByPos(int pos) {
Uri uri = ContentUris.withAppendedId(Articles.CONTENT_POS_URI, pos);
String[] projection = new String[] {
Articles.ID,
Articles.TITLE,
Articles.ABSTRACT,
Articles.URL
};
Cursor cursor = resolver.query(uri, projection, null, null, Articles.DEFAULT_SORT_ORDER);
if (!cursor.moveToFirst()) {
return null;
}
int id = cursor.getInt(0);
String title = cursor.getString(1);
String abs = cursor.getString(2);
String url = cursor.getString(3);
return new Article(id, title, abs, url);
}
}
我们不分析详细过程,首先BulkCursorToCursorAdaptor对象里面的成员变量mBulkCursor通过进程间通信的方式,找到CursorToBulkCursorAdaptor对象,通过里面的成员函数mCursor查询出数据,并且保存在mWindows所指向的匿名共享内存。
而BulkCursorToCursorAdaptor通过成员变量mWindow来访问相同的匿名共享内存的。这样MainActivity就获取了数据。
Android Content Provider在应用程序之间共享数据的原理分析,,
Android Content Provider在应用程序之间共享数据的原理分析