ContentProvider啟動(dòng)流程示例解析
正文
ContentProvider是內(nèi)容提供者,可以跨進(jìn)程提供數(shù)據(jù)。
大家都知道,ContentProvider的啟動(dòng),是在Application的onCreate方法之前的,所以ContentProvider的初始化時(shí)間會(huì)影響整個(gè)App的啟動(dòng)速度。
那ContentProvider啟動(dòng)流程具體是什么樣的呢?讓我們進(jìn)入源碼的世界來(lái)一探究竟。
App啟動(dòng)
App啟動(dòng)時(shí),AMS會(huì)通過(guò)跨進(jìn)程Binder調(diào)用,訪(fǎng)問(wèn)到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) {
// 拼接AppBindData,發(fā)送給ActivityThread的H
sendMessage(H.BIND_APPLICATION, data);
}
這個(gè)方法主要作用是,拼接AppBindData,發(fā)送給ActivityThread中的Handler mH。在這個(gè)Handler中,會(huì)處理Message,然后調(diào)用handleBindApplication(data)方法。
private void handleBindApplication(AppBindData data) {
final InstrumentationInfo ii;
// 創(chuàng)建 mInstrumentation 實(shí)例
if (ii != null) {
//創(chuàng)建ContextImpl
final ContextImpl appContext = ContextImpl.createAppContext(this, pi);
try {
//創(chuàng)建mInstrumentation實(shí)例
final ClassLoader cl = appContext.getClassLoader();
mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {}
} else {
mInstrumentation = new Instrumentation();
}
Application app;
try {
// 創(chuàng)建 Application 實(shí)例
app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// 如果不是backup模式,則調(diào)用installContentProvider,啟動(dòng)ContentProvider
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
//啟動(dòng)ContentProvider
installContentProviders(app, data.providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
try {
//調(diào)用Application的onCreate
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) { }
}
}
這個(gè)方法非常長(zhǎng),主要做的事情有以下四點(diǎn):
- 創(chuàng)建一個(gè)
ContentImpl對(duì)象 - 創(chuàng)建一個(gè)
Instrument對(duì)象 - 創(chuàng)建
Application實(shí)例 - 如果不是
backup模式,調(diào)用installContentProviders,啟動(dòng)ContentProvider - 調(diào)用
Application的onCreate方法
installContentProviders
private void installContentProviders(Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
// 遍歷所有的providers
for (ProviderInfo cpi : providers) {
// 開(kāi)始啟動(dòng)ContentProvider
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
results.add(cph);
}
// 將成功啟動(dòng)的provider存儲(chǔ)到AMS的mProviderMap中
ActivityManager.getService().publishContentProviders(getApplicationThread(), results);
}
這個(gè)方法,循環(huán)遍歷所有待啟動(dòng)的ContentProvider,調(diào)用installProvider啟動(dòng)。
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
// 反射創(chuàng)建ContentProvider
final java.lang.ClassLoader cl = c.getClassLoader();
LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
localProvider = cl.loadClass(className).newInstance();
provider = localProvider.getIContentProvider();
// 調(diào)用ContentProvider的attachInfo方法
localProvider.attachInfo(c, info);
}
這個(gè)方法,通過(guò)反射創(chuàng)建ContentProvider,然后調(diào)用attachInfo方法。
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
// 調(diào)用onCreate方法
ContentProvider.this.onCreate();
}
在ContentProvider的attachInfo方法中,會(huì)調(diào)用onCreate方法,完成ContentProvider的啟動(dòng)。
以上就是ContentProvider啟動(dòng)流程示例解析的詳細(xì)內(nèi)容,更多關(guān)于ContentProvider啟動(dòng)流程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android自定義圓形View實(shí)現(xiàn)小球跟隨手指移動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android自定義圓形View實(shí)現(xiàn)小球跟隨手指移動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
Flutter有無(wú)狀態(tài)類(lèi)與State及生命周期詳細(xì)介紹
這篇文章主要介紹了Flutter無(wú)狀態(tài)類(lèi)、有狀態(tài)類(lèi)、State、生命周期,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09
android項(xiàng)目手機(jī)衛(wèi)士來(lái)電顯示號(hào)碼歸屬地
由于詐騙電話(huà)越來(lái)越猖狂,號(hào)碼歸屬地顯示越來(lái)越重要,本篇文章主要介紹了android手機(jī)衛(wèi)士來(lái)電顯示號(hào)碼歸屬地,有要的朋友可以了解一下。2016-10-10
Android利用ContentProvider獲取本地?cái)?shù)據(jù)的方法
這篇文章主要介紹了Android利用ContentProvider獲取本地?cái)?shù)據(jù)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
Android實(shí)現(xiàn)界面左右滑動(dòng)切換功能
相信大家一定都使用過(guò)手機(jī)QQ和微信之類(lèi)的軟件,當(dāng)我們使用時(shí)不難發(fā)現(xiàn)其界面的切換不僅可以通過(guò)點(diǎn)擊頁(yè)標(biāo)簽來(lái)實(shí)現(xiàn),還可以通過(guò)左右滑動(dòng)來(lái)實(shí)現(xiàn)的,下面小編給大家介紹下如何實(shí)現(xiàn)這個(gè)功能2016-12-12

