
ContentProvider 作为 Android 四大组件中的一种,为我们提供了不同进程甚至是不同应用程序之间共享数据的机制。ContentProvider 的生命周期默认在 Application onCreate() 之前,而且都是在主线程创建的,这和其他四大组件是不同的ContentProvider 多进程模式,它可以和 AndroidManifest 中的 multiprocess 属性结合使用ContentProvider 进行跨进程数据传递时,利用Binder与内存共享机制,就是通过 Binder 传递 CursorWindow 对象内部的匿名共享内存的文件描述符。这样在跨进程传输中,结果数据并不需要跨进程传输,而是在不同进程中通过传输的匿名共享内存文件描述符来操作同一块匿名内存,这样来实现不同进程访问相同数据的目的。ContentProvider 内容提供者,用于对外提供数据ContentResolver.notifyChange(uri)发出消息ContentResolver 内容解析者,用于获取内容提供者提供的数据ContentObserver 内容监听器,可以监听数据的改变状态ContentResolver.registerContentObserver()监听消息。ContentProvider 启动会伴随进程的启动,在ActivityManagerService中,启动进程是由startProcessLocked方法来完成的,内部通过Process的start方法来完成一个新的进程启动。
ActivityThread的main方法
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
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");
}main方法是一个静态方法,首先创建ActivityThread,然后调用attach方法进行一系列的数据操作,再开启主线程Looper循环。
attach方法
private void attach(boolean system) {
......
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
......
}ActivityManager.getService()实质上就是ActivityManagerService,所以最终调用的是ActivityManagerService的attachApplication方法 ,内部调用attachApplicationLocked,然后又调用ApplicationThread的bindApplication方法进行进程间调用。
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
sendMessage(H.BIND_APPLICATION, data);
}最后通过handler发送一个消息,调用ActivityTread的handleBindApplication方法。
首先创建ContextImpl与Instrumentation对象
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
&quot;Unable to instantiate instrumentation &quot;
+ data.instrumentationName + &quot;: &quot; + e.toString(), e);
}
app = data.info.makeApplication(data.restrictedBackupMode, null);
启动当前进程ContentProvider并调用onCreate方法
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled &quot;at some point&quot;.
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
private void installContentProviders(
Context context, List&lt;ProviderInfo&gt; providers) {
final ArrayList&lt;ContentProviderHolder&gt; results = new ArrayList&lt;&gt;();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append(&quot;Pub &quot;);
buf.append(cpi.authority);
buf.append(&quot;: &quot;);
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
ActivityManager.getService().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
最后调用localProvider.attachInfo(c, info);完成ContentProvider的onCreate操作
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
mNoPerms = testing;
/*
* Only allow it to be set once, so after the content service gives
* this to us clients can&#039;t change it.
*/
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 &amp; ProviderInfo.FLAG_SINGLE_USER) != 0;
setAuthorities(info.authority);
}
ContentProvider.this.onCreate();
}
}
最后调用Application的onCreate
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
&quot;Unable to create application &quot; + app.getClass().getName()
+ &quot;: &quot; + e.toString(), e);
}
}ContentProvider已经完成所有的过程,这样ActivityManager就可以可以访问这个ContentProvider,并通过接口来访问它。