热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidContentProvider在应用程序之间共享数据的原理分析

本文参考Android应用程序组件ContentProvider在应用程序之间共享数据的原理分析http:blog.csdn.netluoshengyangarticledetai

       本文参考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 dealers
		CursorWindow 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        我们这里只关注window.writeToParcel(data, 0)。详细解释请看对应的博客或者图书。

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


       如图:第三步

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

       ----ContentProviderNative.java

abstract public class ContentProviderNative extends Binder implements IContentProvider {
	......

	@Override
	public 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[] projection
					int num = data.readInt();
					String[] projection = null;
					if (num > 0) {
						projection = new String[num];
						for (int i = 0; i  0) {
						selectiOnArgs= new String[num];
						for (int i = 0; i        其中,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在应用程序之间共享数据的原理分析


推荐阅读
  • packagetest;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOE ... [详细]
  • 22.Container With Most Water(能装最多水的容器)
    thecontainercontainsthemos ... [详细]
  • 【自制小工具】代码生成器
    【自制小工具】代码生成器陆陆续续接触过好几款代码生成工具,发现确实好用,但都会有那么点不完善的地方,所以索性就自己做一个吧。界面非常简单,反正是自己用的,简单点用起来也方便上图:左 ... [详细]
  • 论文阅读及复现 | Improved Semantic Representations From TreeStructured Long ShortTerm Memory Networks
    两种形式的LSTM变体Child-SumTree-LSTMsN-aryTree-LSTMshttps:paperswithcode.compaperimproved-semanti ... [详细]
  • 看这里,教你如何快速将pdf文件翻译成中文
    因为网上下载的PDF资料,往往掺杂着一些英文,所以中英文翻译是一件很平常的事,毕竟不是每个人的英文都那么好,轻轻松松的就能够看完一篇英文的文件,那么,我们就要寻找翻译工具来帮助我们 ... [详细]
  • 以SOA服务为导向的信息系统构建是通过有计划地构建信息系统时,一种简单而有柔性的方法,就是组件化与服务导向架构。过去的信息系统,是在使用者需要新功能时才开发的,也就是响应不同时 ... [详细]
  • 简单动态字符串redis里面很多地方都用到了字符串,我们知道redis是一个键值对存储的非关系型数据库,那么所有的key都是用字符串存储的,还有字符串类型,这些都是用字符串存储的 ... [详细]
  • 例子如Table表有性别字段,1代表男2代表女、3代表中性、还有没填就代表未说明selectid,decode(sex,'1','男', ... [详细]
  • 接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对 ... [详细]
  • C#的Type对象的简单应用
    通过Type对象可以获取类中所有的公有成员直接贴代码:classMyClass{privatestringname;privateintid;publicstringcity;pu ... [详细]
  • 作业迁移
    背景:数据库服务器更换,1、数据库迁移(BACKUPRESTORE);2、数据库登录名用户迁移(注意孤立用户);3、作业迁移数据库迁移,备份数据库、拷贝备份文件到新服务器,还原数据 ... [详细]
  • Linux     系统安装
    Linux系统安装linux系统安装准备工作电脑、u盘、光盘、网络、硬盘主要使用光盘、网络虚拟化软件vmwarevi ... [详细]
  • 定义:定义两个数论函数\(f\)、\(g\)的Dirichlet卷积为:\[\left(f*g\right)\left(n\right)\sum_{d|n}f\left(d\rig ... [详细]
  • rbac 4表 常规设计
    rbac4表常规设计设计模型:1、管理员表(users)Schema::create('users',function(Blueprint$table){$tabl ... [详细]
  • 读书这件事
    没事晒下自己的借书清单。60多本了,不知道自己一本子能读多少本?可惜的就是没写读书笔记,都是一些泛读。图书馆要 ... [详细]
author-avatar
yyjj7212
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有