ContentProvider啟動流程示例解析
正文
ContentProvider
是內容提供者,可以跨進程提供數據。
大傢都知道,ContentProvider
的啟動,是在Application的onCreate
方法之前的,所以ContentProvider
的初始化時間會影響整個App的啟動速度。
那ContentProvider
啟動流程具體是什麼樣的呢?讓我們進入源碼的世界來一探究竟。
App啟動
App啟動時,AMS會通過跨進程Binder
調用,訪問到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,發送給ActivityThread的H sendMessage(H.BIND_APPLICATION, data); }
這個方法主要作用是,拼接AppBindData
,發送給ActivityThread
中的Handler mH
。在這個Handler
中,會處理Message
,然後調用handleBindApplication(data)
方法。
private void handleBindApplication(AppBindData data) { final InstrumentationInfo ii; // 創建 mInstrumentation 實例 if (ii != null) { //創建ContextImpl final ContextImpl appContext = ContextImpl.createAppContext(this, pi); try { //創建mInstrumentation實例 final ClassLoader cl = appContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) {} } else { mInstrumentation = new Instrumentation(); } Application app; try { // 創建 Application 實例 app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // 如果不是backup模式,則調用installContentProvider,啟動ContentProvider if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { //啟動ContentProvider installContentProviders(app, data.providers); mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } try { //調用Application的onCreate mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { } } }
這個方法非常長,主要做的事情有以下四點:
- 創建一個
ContentImpl
對象 - 創建一個
Instrument
對象 - 創建
Application
實例 - 如果不是
backup
模式,調用installContentProviders
,啟動ContentProvider
- 調用
Application
的onCreate
方法
installContentProviders
private void installContentProviders(Context context, List<ProviderInfo> providers) { final ArrayList<ContentProviderHolder> results = new ArrayList<>(); // 遍歷所有的providers for (ProviderInfo cpi : providers) { // 開始啟動ContentProvider ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); results.add(cph); } // 將成功啟動的provider存儲到AMS的mProviderMap中 ActivityManager.getService().publishContentProviders(getApplicationThread(), results); }
這個方法,循環遍歷所有待啟動的ContentProvider
,調用installProvider
啟動。
private ContentProviderHolder installProvider(Context context, ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) { // 反射創建ContentProvider final java.lang.ClassLoader cl = c.getClassLoader(); LoadedApk packageInfo = peekPackageInfo(ai.packageName, true); localProvider = cl.loadClass(className).newInstance(); provider = localProvider.getIContentProvider(); // 調用ContentProvider的attachInfo方法 localProvider.attachInfo(c, info); }
這個方法,通過反射創建ContentProvider
,然後調用attachInfo
方法。
private void attachInfo(Context context, ProviderInfo info, boolean testing) { // 調用onCreate方法 ContentProvider.this.onCreate(); }
在ContentProvider
的attachInfo
方法中,會調用onCreate
方法,完成ContentProvider
的啟動。
以上就是ContentProvider啟動流程示例解析的詳細內容,更多關於ContentProvider啟動流程的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Android那兩個你碰不到但是很重要的類之ActivityThread
- 詳解Android ContentProvider的基本原理和使用
- Android Service完整實現流程分析
- Android那兩個你碰不到但是很重要的類之ViewRootImpl
- Android ContentProvider基礎應用詳解