文章目录
ContentProvider是一种内容共享性组件,它通过Binder向其他组件乃至其他应用提供数据。
首先来看一下流程图:
一个应用的入口方法为ActivityThread的main方法,该方法是一个静态方法,在main方法中会创建ActivityThread的实例并创建主线程的消息队列,然后在ActivityThread的attach方法中会远程调用AMS的attachApplication方法并将ApplicationThread对象提供给AMS,ApplicationThread是一个Binder对象,它的接口是IApplicattionThread,它主要用于ActivityThread和AMS之间通信。
访问ContentProvider需要通过ContentResolver,它是一个抽象类,通过Context的getContentResolver方法获取的实际上是ApplicationContentResolver对象,该类继承了ContentResolver并实现了ContentResolver中的抽象方法。通过ContentProvider的四个方法中任何一个都可以触发ContentProvider的启动。这里选择query方法。
ContentProvider的query方法首先会获取IContentProvider对象,最终会通过ApplicationContentResolver的acquireProvider方法,该方法没有做任何逻辑,直接调用了ActivityThread的acquireExistingProvider方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) { final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; } IActivityManager.ContentProviderHolder holder = null; try { holder = ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable); } catch (RemoteException ex) { } if (holder == null) { Slog.e(TAG, "Failed to find provider info for " + auth); return null; } // Install provider will increment the reference count for us, and break // any ties in the race. holder = installProvider(c, holder, holder.info, true /*noisy*/, holder.noReleaseNeeded, stable); return holder.provider; }
|
上面代码中首先会从ActivityThread中查找是否已经存在ContentProvider,如果存在就直接返回,ActivityThread中通过mProviderMap来存储已经启动的ContentProvider对象,该容器的声明如下:
1
| final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap= new ArrayMap<ProviderKey, ProviderClientRecord>();
|
如果不存在就发送一个进程间请求给AMS让其启动,再通过installProvider方法来修改引用计数。
AMS是通过startProcessLocked方法来完成进程的启动,内部主要通过Process的start方法来完成进程的启动,新进程启动后的入口方法为ActivityThread的main方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) { ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
|
在该方法中首先会调用ActivityThread的实例并调用attach方法进行初始化,然后进行消息循环,attach方法会将ApplicationThread对象通过AMS的attachApplication方法跨进程传给AMS,最终完成Contentprovider的创建。
1 2 3 4
| try { mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { }
|
APS的attachApplication方法调用了attachApplicationLocked方法,该方法又调用了ApplicationThread的bindApplication方法
1 2 3 4 5 6 7
| thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked());
|
ApplicationThread的bindApplication方法发送一个BIND_APPLICATION类型定位消息给mH,mH收到消息后会调用ActivityThread的handleBindApplication方法,该方法就完成了Application的创建以及Contentprovider的创建,可以分为四步:
1 创建ContextImpl和Instrumentation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ContextImpl instrContext = ContextImpl.createAppContext(this, pi); try { java.lang.ClassLoader cl = instrContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate instrumentation " + data.instrumentationName + ": " + e.toString(), e); } mInstrumentation.init(this, instrContext, appContext, new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
|
2 创建Application对象
1 2
| Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app;
|
3 启动当前进程的ContentProvider并调用其中onCreate方法
1 2 3 4 5 6 7
| List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); }
|
installContentProviders完成的ContentProvider的启动工作,首先会遍历当前进程的ProviderInfo的列表,并一一调用installProvider方法来启动他们,然后将启动的ContentProvider发布到AMS中,AMS会把他们存储在ProviderMap中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| private void installContentProviders( Context context, List<ProviderInfo> providers) { final ArrayList<IActivityManager.ContentProviderHolder> results = new ArrayList<IActivityManager.ContentProviderHolder>(); for (ProviderInfo cpi : providers) { if (DEBUG_PROVIDER) { StringBuilder buf = new StringBuilder(128); buf.append("Pub "); buf.append(cpi.authority); buf.append(": "); buf.append(cpi.name); Log.i(TAG, buf.toString()); } IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); if (cph != null) { cph.noReleaseNeeded = true; results.add(cph); } } try { ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results); } catch (RemoteException ex) { } }
|
下面来看一下COntentProvider对象的创建过程,在installProvider方法中有下面一段代码,通过类加载器完成对象创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| final java.lang.ClassLoader cl = c.getClassLoader(); localProvider = (ContentProvider)cl. loadClass(info.name).newInstance(); provider = localProvider.getIContentProvider(); if (provider == null) { Slog.e(TAG, "Failed to instantiate class " + info.name + " from sourceDir " + info.applicationInfo.sourceDir); return null; } if (DEBUG_PROVIDER) Slog.v( TAG, "Instantiating local provider " + info.name); // XXX Need to create the correct context for this provider. localProvider.attachInfo(c, info);
|
上面代码还会调用COntentProvider的attachInfo方法来调用他的onCreate方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private void attachInfo(Context context, ProviderInfo info, boolean testing) { mNoPerms = testing; if (mContext == null) { mContext = context; if (context != null) { mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); } mMyUid = Process.myUid(); if (info != null) { setReadPermission(info.readPermission); setWritePermission(info.writePermission); setPathPermissions(info.pathPermissions); mExported = info.exported; mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0; setAuthorities(info.authority); } ContentProvider.this.onCreate(); } }
|
到此为止onCreate方法已经被调用,意味着ContentProvider已经启动完成。
4 调用Application的onCreate方法
经过上面四个步骤,ContentPorovider已经成功启动,然后其他应用就可通过AMS来访问这个ContentProvider,拿到该对象之后就可以通过它所提供的接口来访问它了。
未经许可不得转载,转载请注明zilianliuxue的blog,本人保留所有版权。