本文参考Android应用程序组件Content Provider在应用程序之间共享数据的原理分析http://blog.csdn.net/luoshengyang/article/details/6967204和《Android系统源代码情景分析》,作者罗升阳。

0、总图流程图如下:

总体类图:



1、MainActivity进程向AriticlesProvider进程发送IContentProvider.QUERY_TRANSACTION



如图:第一步

~/Android/frameworks/base/core/java/android/content

----ContentProviderNative.java

final class ContentProviderProxy implements IContentProvider {......public Cursor query(Uri url, String[] projection, String selection,String[] selectionArgs, String sortOrder) throws RemoteException {//TODO make a pool of windows so we can reuse memory dealersCursorWindow window = new CursorWindow(false /* window will be used remotely */);BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();IBulkCursor bulkCursor = bulkQueryInternal(url, projection, selection, selectionArgs, sortOrder,adaptor.getObserver(), window,adaptor);if (bulkCursor == null) {return null;}return adaptor;}......
(1)创建了CursorWindow对象。

(2)创建类BulkCursorToCursorAdaptor对象。
(3)调用bulkQueryInternal。


~/Android/frameworks/base/core/java/android/content

----ContentProviderNative.java

final class ContentProviderProxy implements IContentProvider{......private IBulkCursor bulkQueryInternal(Uri url, String[] projection,String selection, String[] selectionArgs, String sortOrder,IContentObserver observer, CursorWindow window,BulkCursorToCursorAdaptor adaptor) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IContentProvider.descriptor);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(observer.asBinder());window.writeToParcel(data, 0);// Flag for whether or not we want the number of rows in the// cursor and the position of the "_id" column index (or -1 if// non-existent).  Only to be returned if binder != null.final boolean wantsCursorMetadata = (adaptor != null);data.writeInt(wantsCursorMetadata ? 1 : 0);mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);DatabaseUtils.readExceptionFromParcel(reply);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);}}}data.recycle();reply.recycle();return bulkCursor;}......}
我们这里只关注window.writeToParcel(data, 0)。详细解释请看对应的博客或者图书。

如图:第二步,省略binder_transaction传输过程,因为上面已经分析过了。


如图:第三步

~/Android/frameworks/base/core/java/android/content

----ContentProviderNative.java

abstract public class ContentProviderNative extends Binder implements IContentProvider {......@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags)throws RemoteException {try {switch (code) {case QUERY_TRANSACTION:{data.enforceInterface(IContentProvider.descriptor);Uri url = Uri.CREATOR.createFromParcel(data);// String[] projectionint num = data.readInt();String[] projection = null;if (num > 0) {projection = new String[num];for (int i = 0; i < num; i++) {projection[i] = data.readString();}}// String selection, String[] selectionArgs...String selection = data.readString();num = data.readInt();String[] selectionArgs = null;if (num > 0) {selectionArgs = new String[num];for (int i = 0; i < num; i++) {selectionArgs[i] = data.readString();}}String sortOrder = data.readString();IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder());CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);// Flag for whether caller wants the number of// rows in the cursor and the position of the// "_id" column index (or -1 if non-existent)// Only to be returned if binder != null.boolean wantsCursorMetadata = data.readInt() != 0;IBulkCursor bulkCursor = bulkQuery(url, projection, selection,selectionArgs, sortOrder, observer, window);reply.writeNoException();if (bulkCursor != null) {reply.writeStrongBinder(bulkCursor.asBinder());if (wantsCursorMetadata) {reply.writeInt(bulkCursor.count());reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(bulkCursor.getColumnNames()));}} else {reply.writeStrongBinder(null);}return true;}......}} catch (Exception e) {DatabaseUtils.writeExceptionToParcel(reply, e);return true;}return super.onTransact(code, data, reply, flags);}......}
其中,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就获取了数据。

如果是删除数据,可能不需要读写匿名共享内存,只要通过mBulkCursor通过进程间通信的方式的操作和读取返回结果。

更多相关文章

  1. Android开发面试经——常见面试官提问Android题②
  2. INSTALL_FAILED_MISSING_FEATURE
  3. Android5.1.1-APK签名校验分析和修改源码绕过签名校验
  4. Android的跨进程通信
  5. Android(安卓)Binder机制,虚拟机
  6. Android(安卓)应用进程启动流程
  7. android开机动画播放流程
  8. android 内存回收原理
  9. 疯狂安卓Android自学笔记

随机推荐

  1. Xamarin C# Android(安卓)for Windows 安
  2. Cydia for Android
  3. Android的四大组件
  4. Android(安卓)Handler机制3之SystemClock
  5. Android(安卓)自定义圆角按钮
  6. Android窗口机制(四)ViewRootImpl与View和W
  7. Android(安卓)Handler机制11之Handler机
  8. Android知识体系结构概览
  9. Android中UI设计的一些技巧!!!
  10. Android(安卓)4.0 访问WebService 出现 a