ContentProvider query调用过程源码分析(Android Q)
ContentProvider 是 Android 的四大组件之一,可以很方便的跨进程查询数据,那么 Android 系统是如何实现 ContentProvider 的查询等操作的呢?
ContentProvider 的使用示例
我们首先来看一个 ContentProvider 调用示例:
public void readData(String selection) { Cursor cursor = null; try { cursor = context.getContentResolver() .query(getTableUri(), null, selection, null, null); …… } catch (Exception e) { LogX.e(TAG, SUB_TAG, getName() + "; " + e.toString()); } }
这里通过 context 对象的 getContentResolver() 方法,就可以操作 ContentProvider 存储的数据了,如何实现的呢?我们通过源码来分析整个过程。
ContentResolver
ContentResolver 类是一个很关键的类,我们实际使用 ContentProvider 的数据时,都是通过该类的实例来操作的。
ContextImpl 的 getContentResolver() 方法
我们来看 context.getContentResolver(),这里的 context 的实现类是 ContextImpl类(不清楚的可以查看前文),源码如下:
@Override public ContentResolver getContentResolver() { return mContentResolver; }
这里直接返回了一个 ContentResolver 对象,该对象是什么呢?又是在哪赋值的呢?
ContentResolver 对象的创建
@UnsupportedAppUsage private final ApplicationContentResolver mContentResolver; private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread, @NonNull LoadedApk packageInfo, @Nullable String splitName, @Nullable IBinder activityToken, @Nullable UserHandle user, int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) { …… mContentResolver = new ApplicationContentResolver(this, mainThread); }
mContentResolver 是 ApplicationContentResolver 的一个实例对象,它在 ContextImpl 构造函数中创建的。ApplicationContentResolver 类是 ContextImpl 的一个内部类。
ContentResolver 的 query 方法
@Override public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { …… //获取目标 ContentProvider 对象。 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 { //调用目标 ContentProvider 对象的 query 方法查询数据。 qCursor = unstableProvider.query(mPackageName, uri, projection, queryArgs, remoteCancellationSignal); } catch (DeadObjectException e) {//ContentProvider 所在进程已死 // 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, queryArgs, remoteCancellationSignal); } if (qCursor == null) { return null; } …… //将 Cursor 对象包装到 CursorWrapperInner 对象中。 final IContentProvider provider = (stableProvider != null) ? stableProvider : acquireProvider(uri); final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider); stableProvider = null; qCursor = null; return wrapper; } …… }
ContentResolver 的 query 方法主要做了以下几个操作:
- 获取目标 ContentProvider 对象。
- 调用目标 ContentProvider 对象的 query 方法查询数据。
- 将 Cursor 对象包装到 CursorWrapperInner 对象中,并返回。
这里的关键点是,如何获取目标 ContentProvider 对象,也就是 acquireUnstableProvider 方法的实现。
acquireUnstableProvider 方法是由 ContentResolver 的子类 ApplicationContentResolver(ContextImpl 的一个内部类)实现的。
acquireUnstableProvider 方法
private final ActivityThread mMainThread; @Override protected IContentProvider acquireUnstableProvider(Context c, String auth) { return mMainThread.acquireProvider(c, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), false); }
其实,这里直接调用了主线程对象 ActivityThread 对象的 acquireProvider 方法。
ActivityThread 对象的 acquireProvider 方法
public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) { //如果 ContentProvider 已经安装,则直接从缓存中获取即可。 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; } …… ContentProviderHolder holder = null; try { synchronized (getGetProviderLock(auth, userId)) { //调用 AMS 获取 ContentProvider 对象。 holder = ActivityManager.getService().getContentProvider( getApplicationThread(), c.getOpPackageName(), auth, userId, stable); } } …… //安装、发布 ContentProvider 对象。参考:https://blog.csdn.net/u0/article/details/ holder = installProvider(c, holder, holder.info, true /*noisy*/, holder.noReleaseNeeded, stable); return holder.provider; }
- 如果 ContentProvider 已经安装,则直接从缓存中获取即可。
- 调用 AMS 获取 ContentProvider 对象(远程)。
- 安装、发布 ContentProvider 对象。参考:https://blog.csdn.net/u0/article/details/
完成后,ContentProvider 已经准备好了,之后的调用,我们都可以通过 ActivityThread 对象的 acquireProvider 方法,直接从缓存中获取了。
PS:更多精彩内容,请查看 –> 《Android底层原理解析》
PS:更多精彩内容,请查看 –> 《Android底层原理解析》
PS:更多精彩内容,请查看 –> 《Android底层原理解析》
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212027.html原文链接:https://javaforall.net
