Android 基础总结:(十一)ContentResolver与ContentProvider如何关联在一起的

Application是一个完整的应用,比如某个apk,它对应一个Application,它里面可能包含n个Activity。

涉及到的类

froyo/frameworks/base/core/java/android/app/ApplicationContext.java
froyo/frameworks/base/core/java/android/app/ActivityThread.java
froyo/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

当我们启动手机之后,如果需要启动一个activity,ActivityThread,ActivityManagerService就开始发挥作用了,这里不做细述。

当我们真正的启动一个activity的时候,我们会把当前Application的ApplicationContext传进去,ApplicationContext实例持有一个mContextResolver对象,该对象对应于ApplicationContext的内部类ApplicationContentResolver。

当activity调用getContentResolver()时,我们实际调用的是当前ApplicationContext中的mContextResolver.

我们来看看效果图:

由于黑色的继承关系,我们可以得到红色的调用关系我们看看效果图就知道了,它们两个是怎么样跳过文件来直接联系在一起的。这样的话我们就省去了很多环节,也给我们节省了时间这样的话我们也不容易出错,这样以来我们就会大大的提高了我们的工作效率,

代码片段如下:

Activity调用ContextWrapper的方法

getContentResolver() {
	mBase.getContentResolver();
}

然后会调用到ApplicationContext的方法

getContentResolver() {
	return mContentResolver;
}

Java代码:

mContentResolve r = new ApplicationContentResolver(this, mainThread);
private static final class ApplicationContentResolver extends
		ContentResolver {
	public ApplicationContentResolver(Context context,
			ActivityThread mainThread) {
		super(context);
		mMainThread = mainThread;
	}
	@Override
	protected IContentProvider acquireProvider(Context context, String name) {
		return mMainThread.acquireProvider(context, name);
	}
	@Override
	public boolean releaseProvider(IContentProvider provider) {
		return mMainThread.releaseProvider(provider);
	}
	private final ActivityThread mMainThread;
}

当执行mContentResolver.query()的时候,我们会调用父类ContentResolver的query();

public final Cursor query(Uri uri, String[] projection, String selection,
		String[] selectionArgs, String sortOrder) {
	IContentProvider provider = acquireProvider(uri);
	if (provider == null) {
		return null;
	}
	try {
		Cursor qCursor = provider.query(uri, projection, selection,
				selectionArgs, sortOrder);
		if (qCursor == null) {
			releaseProvider(provider);
			return null;
		}
		// CursorWrapperInner光标对象
		return new CursorWrapperInner(qCursor, provider);
	} catch (RemoteException e) {
		releaseProvider(provider);
		return null;
	} catch (RuntimeException e) {
		releaseProvider(provider);
		throw e;
	}
}
public final IContentProvider acquireProvider(Uri uri) {
	if (!SCHEME_CONTENT.equals(uri.getScheme())) {
		return null;
	}
	String auth = uri.getAuthority();
	if (auth != null) {
		return acquireProvider(mContext, uri.getAuthority());
	}
	return null;
}

此时,会调用子类实例aquireProvider(Context,name);

mMainThread.acquireProvider (context, name);

Java代码:

public final IContentProvider acquireProvider(Context c, String name) {
	IContentProvider provider = getProvider(c, name);
	if (provider == null)
		return null;
	IBinder jBinder = provider.asBinder(); // 获得binder对象,跨进程传递数据。
	synchronized (mProviderMap) {
		ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
		if (prc == null) {
			mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
		} else {
			prc.count++;
		} // end else
	} // end synchronized
	return provider;
}
private final IContentProvider getProvider(Context context, String name) {
	synchronized (mProviderMap) {
		final ProviderRecord pr = mProviderMap.get(name); // ActivityThread中持有所有的Provider的实例
		if (pr != null) {
			return pr.mProvider;
		}
	}
	// 如果确实没有,则查找,并install,再没有就直接抛异常了。
	IActivityManager.ContentProviderHolder holder = null;
	try {
		holder = ActivityManagerNative.getDefault().getContentProvider(
				getApplicationThread(), name);
	} catch (RemoteException ex) {
	}
	if (holder == null) {
		Log.e(TAG, "Failed to find provider info for " + name);
		return null;
	}
	if (holder.permissionFailure != null) {
		throw new SecurityException("Permission 
				+ holder.permissionFailure + " required for provider
				+ name);
	}
	IContentProvider prov = installProvider(context, holder.provider,
			holder.info, true);
	// Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
	if (holder.noReleaseNeeded || holder.provider == null) {
		// We are not going to release the provider if it is an external
		// 供应商,不在乎被释放,或如果它是
		// 本地提供运行这一过程。
		// Log.i(TAG, "*** NO RELEASE NEEDED");
		synchronized (mProviderMap) {
			mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(
					10000));
		}
	}
	return prov;
}

上面的代码if(provider==null)后面有一个返回值,这个返回值一定要是空,不要写别的,后面的判断我们也都判断为空,这样我们就完成了contentResolver与contentProvider联系在一起了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值