ContentProvider的工作过程
ContentProvider的调用过程
ContentProvider所在的进程启动时,ContentProvider会同时启动并发布到AMS中。ContentProvider的onCreate要先于Application的onCreate而执行。
访问ContentProvider需要通过ContentResolver,ContentResolver是一个抽象类,实际实现者是ContentImpl中的ApplicationContentResolver
private static final class ApplicationContentResolver extends ContentResolver {
@Override
protected IContentProvider acquireProvider(Context context, String auth) {
return mMainThread.acquireProvider(context,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), true);
}
//...
}
通过ContentResolver的四个方法的任意一个,都可以触发ContentProvider的启动(如果还没有启动的话)
这里以query()示例
public final Cursor query(final Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
CancellationSignal cancellationSignal) {
IContentProvider unstableProvider = acquireUnstableProvider(uri);
IContentProvider stableProvider = null;
//...
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
} catch (DeadObjectException e) {
stableProvider = acquireProvider(uri);
qCursor = stableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
}
//...
}
可以看到,先调用了acquireUnstableProvider(),如果失败,则会调用acquireProvider(),但最终都是通过acquireProvider()来获取ContentProvider
ApplicationContentResolver的acquireProvider方法并没有处理任何逻辑,它直接调用了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);
//启动ContentProvider
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
//安装Provider,增加引用的数量
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
return holder.provider;
}
启动ContentProvider的过程
ContentProvider启动之前,会前启动ContentProvider的进程
启动进程由ActivityManagerService的startProcessLocked()来完成,其内部主要通过Process的start方法来完成一个新进程的启动。
新进程启动后其入口为ActivityThread的main方法。
public static void main(String[] args) {
//...
//Z-创建主线程的消息队列
Looper.prepareMainLooper();
//Z-创建ActivityThread实例
ActivityThread thread = new ActivityThread();
//Z-远程调用AMS的attachApplication方法,进行初始化,并将ApplicationThread对象提供给AMS
thread.attach(false);
//...
Looper.loop();
}
来看ActivityThread#attach()
private void attach(boolean system) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread);
//...
}
再来看ActivityManagerService.attachApplication()
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
再来看ActivityManagerService.attachApplicationLocked()
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
//...
//Z- ApplicationThread.bindApplication
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(),
mCoreSettingsObserver.getCoreSettingsLocked());
//...
return true;
}
再来看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 enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {
//...
//Z- 通过ActivityThread的mH Handler切换到ActivityThread中去执行
sendMessage(H.BIND_APPLICATION, data);
}
Message的发送通过handleBindApplication()来处理
private void handleBindApplication(AppBindData data) {
//...
//1.创建ContextImpl和Instrumentation
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
//...
//2.创建Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
//3.启动当前进程的ContentProvider并调用其onCreate方法
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
//4.调用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
}
其中会调用 installContentProviders()
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
//...
//通过类加载器完成ContentProvider的创建
IActivityManager.ContentProviderHolder cph = installProvider(context,
//...
//通过AMS存储到Map中
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
}
又会调用installProvider()
private IActivityManager.ContentProviderHolder installProvider(Context context,
IActivityManager.ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
//通过类加载器完成ContentProvider的创建
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
//该方法会调用ContentProvider的onCrate方法
localProvider.attachInfo(c, info);
return retHolder;
}
通过调用提供的接口来访问ContentProvider
ContentProvider#query()
public Cursor query(String callingPkg, Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
ICancellationSignal cancellationSignal) {
//...
return ContentProvider.this.query(
uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
//...
}