先給出一個(gè)需要注意的點(diǎn):ContentProvider的onCreate方法比Application的onCreate方法先執(zhí)行. 下面會(huì)給出為什么.
ContentProvider相對(duì)于其他組件來說,用得稍微少一些.很少有APP需要向其他應(yīng)用提供數(shù)據(jù),保護(hù)自己的數(shù)據(jù)都來不及呢.當(dāng)然,除了一些大廠的APP,還有就是手機(jī)自帶的一些應(yīng)用(通訊錄,短信,相冊(cè)等等).ContentProvider可以向其他組件或者其他應(yīng)用提供數(shù)據(jù),其中是通過Binder來進(jìn)行通信的.ContentProvider中的數(shù)據(jù)提供不僅僅只有SQLite 一種方式.當(dāng)其他應(yīng)用訪問ContentProvider時(shí),如果該ContentProvider的進(jìn)程沒有啟動(dòng),那么第一次訪問該ContentProvider就會(huì)觸發(fā)該ContentProvider的的進(jìn)程啟動(dòng).
建議先看一下,之前我寫的系列文章,才能更好的理解本文
- 死磕Android_App 啟動(dòng)過程(含 Activity 啟動(dòng)過程)
- 死磕Android_Service啟動(dòng)流程分析(一)
- 死磕Android_Service綁定流程分析(二)
- 死磕Android_BroadcastReceiver 工作過程
ps: 本文基于API 28的源碼分析的
1. 進(jìn)程的啟動(dòng)
APP啟動(dòng)時(shí)會(huì)啟動(dòng)一個(gè)新的進(jìn)程,該進(jìn)程的入口在ActivityThread的main方法中.
public static void main(String[] args) {
//準(zhǔn)備主線程的Looper
Looper.prepareMainLooper();
//創(chuàng)建ActivityThread實(shí)例,調(diào)用attach方法
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
//主線程的消息循環(huán)啊,開始
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
main方法就那么幾句代碼,我們很方便得看出它的邏輯.Looper的那個(gè)邏輯在死磕Android_Handler機(jī)制你需要知道的一切中已做詳細(xì)講解,這里不再贅述.然后就是會(huì)在main方法里面創(chuàng)建ActivityThread的實(shí)例, 這個(gè)時(shí)候我們只要跟著attach方法進(jìn)入看看干了什么騷操作
private void attach(boolean system, long startSeq) {
......
final IActivityManager mgr = ActivityManager.getService();
mgr.attachApplication(mAppThread, startSeq);
}
attach方法對(duì)我們來說,需要關(guān)注的點(diǎn)就是上面的兩句代碼,其他的非主流程的代碼我都略去了... 又又又又遇到了ActivityManager.getService(),前面的文章提到過特別多次,它就是AMS,IActivityManager是用來與AMS進(jìn)行跨進(jìn)程通信的,這里調(diào)用了AMS的attachApplication方法.
2. 路過AMS
下面是attachApplication方法的源碼
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
return true;
}
這里的thread是ApplicationThread,它繼承了IApplicationThread.Stub,跨進(jìn)程通信,是一個(gè)Binder對(duì)象.所以上面的bindApplication方法是在ApplicationThread中的
3. 又回ActivityThread
下面是ActivityThread中的內(nèi)部類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, boolean autofillCompatibilityEnabled) {
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;
data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
sendMessage(H.BIND_APPLICATION, data);
}
這個(gè)方法沒啥說的,就是賦值一些屬性,然后發(fā)送一個(gè)消息到大名鼎鼎的H這個(gè)Handler,之前的文章也分析過這個(gè)Handler.這個(gè)消息在處理時(shí)就只是調(diào)用了ActivityThread的handleBindApplication方法
private void handleBindApplication(AppBindData data) {
//創(chuàng)建ContextImpl
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
//創(chuàng)建Instrumentation
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
//創(chuàng)建Application
Application app;
app = data.info.makeApplication(data.restrictedBackupMode, null);
//注意,這里是install ContentProvider
installContentProviders(app, data.providers);
//調(diào)用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
}
handleBindApplication方法干了很多事情
- 創(chuàng)建ContextImpl
- 創(chuàng)建Instrumentation
- 創(chuàng)建Application
- 創(chuàng)建ContentProvider,并調(diào)用其onCreate方法
- 調(diào)用Application的onCreate方法
下面我們繼續(xù)深入installContentProviders方法
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
for (ProviderInfo cpi : providers) {
//構(gòu)建ContentProvider
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();
}
}
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
//通過ClassLoader 反射構(gòu)建ContentProvider
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = packageInfo.getAppFactory()
.instantiateProvider(cl, info.name);
//attachInfo方法里面就會(huì)調(diào)用ContentProvider的onCreate方法
localProvider.attachInfo(c, info);
return retHolder;
}
分析上面的代碼,installContentProviders方法會(huì)遍歷所有的Provider, 然后分別構(gòu)建,最后將這些構(gòu)建好的Provider都publish到AMS中.當(dāng)然在installProvider構(gòu)建ContentProvider方法里面,它是調(diào)用了ContentProvider的onCreate方法的,下面請(qǐng)看詳情
ContentProvider.java => attachInfo
public void attachInfo(Context context, ProviderInfo info) {
attachInfo(context, info, false);
}
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
ContentProvider.this.onCreate();
}
當(dāng)然,到了這里,一個(gè)ContentProvider就此啟動(dòng).我們也看到了,ContentProvider的onCreate方法確實(shí)是比Application的onCreate方法先調(diào)用.