Android10 App啟動Activity源碼分析
正文
上一篇:
Android 10 App啟動分析之進程創(chuàng)建篇(一)
上一篇文章,我們探討了App啟動過程中進程創(chuàng)建及初始化的流程,這篇文章我們接著上篇的內容,繼續(xù)探討App的Application和Activity的創(chuàng)建及啟動流程。
ActivityThread的main方法
讓我們把目光聚焦到ActivityThread
的main方法上。
ActivityThread
的源碼路徑為 /frameworks/base/core/java/android/app/ActivityThread
。
public static void main(String[] args) { ... //請注意這句話,主線程Looper在此處做了prepare的操作 Looper.prepareMainLooper(); // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line. // It will be in the format "seq=114" long startSeq = 0; if (args != null) { for (int i = args.length - 1; i >= 0; --i) { if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) { startSeq = Long.parseLong( args[i].substring(PROC_START_SEQ_IDENT.length())); } } } ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq); if (sMainThreadHandler == null) { //獲取主線程的handler,其實就是ActivityThread里的mH變量 sMainThreadHandler = thread.getHandler(); } //開始循環(huán)獲取主線程Message消息 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
繼續(xù)從ActivityThread
的attach方法往下追蹤。
private void attach(boolean system, long startSeq) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { //執(zhí)行此分支 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { ActivityTaskManager.getService().releaseSomeActivities(mAppThread); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }); } else { ... } ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> { synchronized (mResourcesManager) { // We need to apply this change to the resources immediately, because upon returning // the view hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig, null /* compat */)) { updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(), mResourcesManager.getConfiguration().getLocales()); // This actually changed the resources! Tell everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(globalConfig)) { mPendingConfiguration = globalConfig; sendMessage(H.CONFIGURATION_CHANGED, globalConfig); } } } }; ViewRootImpl.addConfigCallback(configChangedCallback); }
上述代碼調用了IActivityManager
的attachApplication
方法,并傳入了當前的ActivityThread
對象以及啟動序列號。我們將目光轉向ActivityManagerService
。
@Override public final void attachApplication(IApplicationThread thread, long startSeq) { if (thread == null) { throw new SecurityException("Invalid application interface"); } synchronized (this) { int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid, callingUid, startSeq); Binder.restoreCallingIdentity(origId); } }
private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { ... mAtmInternal.preBindApplication(app.getWindowProcessController()); final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } else if (instr2 != null) { thread.bindApplication(processName, appInfo, providers, instr2.mClass, profilerInfo, instr2.mArguments, instr2.mWatcher, instr2.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, autofillOptions, contentCaptureOptions); } else { thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, autofillOptions, contentCaptureOptions); } if (profilerInfo != null) { profilerInfo.closeFd(); profilerInfo = null; } // Make app active after binding application or client may be running requests (e.g // starting activities) before it is ready. app.makeActive(thread, mProcessStats); checkTime(startTime, "attachApplicationLocked: immediately after bindApplication"); mProcessList.updateLruProcessLocked(app, false, null); checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked"); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { // todo: Yikes! What should we do? For now we will try to // start another process, but that could easily get us in // an infinite loop of restarting processes... Slog.wtf(TAG, "Exception thrown during bind of " + app, e); app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName)); return false; } // Remove this record from the list of starting applications. mPersistentStartingProcesses.remove(app); if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES, "Attach application locked removing on hold: " + app); mProcessesOnHold.remove(app); boolean badApp = false; boolean didSomething = false; // See if the top visible activity is waiting to run in this process... if (normalMode) { try { didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } // Find any services that should be running in this process... if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked"); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } } ... return true; }
上面這段內容有兩段關鍵的語句,一是調用了 IApplicationThread
的bindApplication
方法;二是調用了ActivityTaskManagerInternal
的attachApplication
方法。我們先來看位于ActivityThread
中的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, AutofillOptions autofillOptions, ContentCaptureOptions contentCaptureOptions) { ... sendMessage(H.BIND_APPLICATION, data); }
方法的結尾,發(fā)送了一條what值為H.BIND_APPLICATION
的消息。
我們去Handler中找到這條消息的代碼段。
switch (msg.what) { case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
private void handleBindApplication(AppBindData data) { // Register the UI Thread as a sensitive thread to the runtime. ... Application app; try { //在這里創(chuàng)建了Application對象 app = data.info.makeApplication(data.restrictedBackupMode, null); // Propagate autofill compat state app.setAutofillOptions(data.autofillOptions); // Propagate Content Capture options app.setContentCaptureOptions(data.contentCaptureOptions); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } } // Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { //在這里調用了Application onCreate方法 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } } // 加載字體資源 FontsContract.setApplicationContextForResources(appContext); if (!Process.isIsolated()) { try { final ApplicationInfo info = getPackageManager().getApplicationInfo( data.appInfo.packageName, PackageManager.GET_META_DATA /*flags*/, UserHandle.myUserId()); if (info.metaData != null) { final int preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { data.info.getResources().preloadFonts(preloadedFontsResource); } } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
app = data.info.makeApplication(data.restrictedBackupMode, null);
Application Context對象
這段代碼是一段關鍵代碼,它創(chuàng)建了Application以及全局的Application Context對象, 我們深入往下看一下:
源碼位置為 frameworks/base/core/java/android/app/LoadedApk.java
。
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } Application app = null; //如果manifest application標簽的name屬性指定了application類,則使用指定的類,否則默認使用android.app.Application String appClass = mApplicationInfo.className; if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; } try { java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "initializeJavaContextClassLoader"); initializeJavaContextClassLoader(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } //創(chuàng)建全局的Application Context ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //創(chuàng)建Application對象 app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); } catch (Exception e) { if (!mActivityThread.mInstrumentation.onException(app, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw new RuntimeException( "Unable to instantiate application " + appClass + ": " + e.toString(), e); } } mActivityThread.mAllApplications.add(app); mApplication = app; if (instrumentation != null) { try { instrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!instrumentation.onException(app, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } // Rewrite the R 'constants' for all library apks. SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(); final int N = packageIdentifiers.size(); for (int i = 0; i < N; i++) { final int id = packageIdentifiers.keyAt(i); if (id == 0x01 || id == 0x7f) { continue; } rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return app; }
static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Application app = (Application)clazz.newInstance(); //在這里將applicationContext設置到application對象中 app.attach(context); return app; }
第一階段,Application的創(chuàng)建與初始化已經至此結束,接下來我們將目光放到ActivityTaskManagerInternal
的attachApplication
方法。
public boolean attachApplication(WindowProcessController wpc) throws RemoteException { synchronized (mGlobalLockWithoutBoost) { return mRootActivityContainer.attachApplication(wpc); } }
進入了RootActivityContainer
中繼續(xù)執(zhí)行。
boolean attachApplication(WindowProcessController app) throws RemoteException { final String processName = app.mName; boolean didSomething = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.get(displayNdx); final ActivityStack stack = display.getFocusedStack(); if (stack != null) { stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList); final ActivityRecord top = stack.topRunningActivityLocked(); final int size = mTmpActivityList.size(); for (int i = 0; i < size; i++) { final ActivityRecord activity = mTmpActivityList.get(i); if (activity.app == null && app.mUid == activity.info.applicationInfo.uid && processName.equals(activity.processName)) { try { if (mStackSupervisor.realStartActivityLocked(activity, app, top == activity /* andResume */, true /* checkConfig */)) { didSomething = true; } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting activity " + top.intent.getComponent().flattenToShortString(), e); throw e; } } } } } if (!didSomething) { ensureActivitiesVisible(null, 0, false /* preserve_windows */); } return didSomething; }
由ActivityStackSupervisor
的realStartActivityLocked
方法去真正準備啟動Activity。
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException { ... try { ... try { ... // Create activity launch transaction. final ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken); final DisplayContent dc = r.getDisplay().mDisplayContent; clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.icicle, r.persistentState, results, newIntents, dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(), r.assistToken)); // Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); ... } catch (RemoteException e) { ... } } finally { endDeferResume(); } ... return true; }
為了解釋清楚上述過程,我們必須先得認識一下ClientTransaction
及其一系列相關的類。
相關聯(lián)的類有以下幾個:ClientTransaction
、TransactionExecutor
、ClientLifecycleManager
以及LaunchActivityItem
,我們一個一個來分析。
LaunchActivityItem
LaunchActivityItem
實現(xiàn)了BaseClientRequest
interface。這個接口里定義了三個十分重要的方法。
- preExecute 在請求前進行預處理
- execute 執(zhí)行請求
- postExecute 執(zhí)行請求后的后續(xù)處理 這種設計方式是不是很眼熟!
AsyncTask
也是基于這種模式設計的,各位讀者不妨自行聯(lián)想類比一下。
LaunchActivityItem
這個類設計的目的是什么呢?從名字上來講,我們很容易想到,它主要的作用就是用來啟動一個Activity的,具體反應在它重載的excute
方法。
@Override public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, mPendingResults, mPendingNewIntents, mIsForward, mProfilerInfo, client, mAssistToken); client.handleLaunchActivity(r, pendingActions, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); }
看到這句話了么,client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
。client
這個對象是什么?我們可以翻閱一下代碼的調用鏈,可以發(fā)現(xiàn)client
是一個ActivityThread
對象,它最終調用的是ActivityThread
中的handleLaunchActivity
方法。
除了LauncherActivityItem
以外,我們還有abstract的ActivityLifecycleItem
類,在這個類中定義了一系列的生命周期狀態(tài),具體如下:
public static final int UNDEFINED = -1; public static final int PRE_ON_CREATE = 0; public static final int ON_CREATE = 1; public static final int ON_START = 2; public static final int ON_RESUME = 3; public static final int ON_PAUSE = 4; public static final int ON_STOP = 5; public static final int ON_DESTROY = 6; public static final int ON_RESTART = 7;
這些狀態(tài)的值基本按照Activity的生命周期的順序,以1為步長遞增定義。為什么這么設計,我們后續(xù)會講到。
除此之外,系統(tǒng)還定義了StopActivityItem
、NewIntentItem
、DestroyActivityItem
等等一系列類似的類,這些類都是為了實現(xiàn)具體的和Activity生命周期有關的任務,并按照 預處理——執(zhí)行——事后處理 的模板編寫業(yè)務。
除此之外,這些類其中有一部分還有一個作用,就是確定客戶端在執(zhí)行事務后最終應處于的生命周期狀態(tài)。
ClientLifecycleManager
生命周期管理類,它能夠組合多個客戶端生命周期變換的請求或回調事務,并將它們作為單個事務執(zhí)行。這個方法里的內容非常簡單,我們主要來關注一下它的scheduleTransaction
的方法。
void scheduleTransaction(ClientTransaction transaction) throws RemoteException { final IApplicationThread client = transaction.getClient(); transaction.schedule(); if (!(client instanceof Binder)) { // If client is not an instance of Binder - it's a remote call and at this point it is // safe to recycle the object. All objects used for local calls will be recycled after // the transaction is executed on client in ActivityThread. transaction.recycle(); }
根據(jù)上述源碼,可以看出它調用了傳入的ClientTransaction
的schedule
方法。
ClientTransaction
ClientTransaction
是一個保存可以發(fā)送到客戶端的消息序列的容器。它包含了三個比較重要的方法, setLifecycleStateRequest
、addCallback
、schedule
,分別用于設置目標生命周期狀態(tài)和事務方法,以及執(zhí)行事務。
我們來看一下schedule
這個方法:
public void schedule() throws RemoteException { mClient.scheduleTransaction(this); }
代碼的內容非常簡單,它將schedule
的操作重新分發(fā)給了mClient
變量,這里的mClient
,指的是ActivityThread
實例。
public void executeTransaction(ClientTransaction transaction) { transaction.preExecute(this); getTransactionExecutor().execute(transaction); transaction.recycle(); }
這里首先調用了這樣一條語句,transaction.preExecute(this)
,用于執(zhí)行事務前的預處理操作。
public void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) { if (mActivityCallbacks != null) { final int size = mActivityCallbacks.size(); for (int i = 0; i < size; ++i) { mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken); } } if (mLifecycleStateRequest != null) { mLifecycleStateRequest.preExecute(clientTransactionHandler, mActivityToken); } }
可以看到,它實際調用了通過setLifecycleStateRequest
和addCallback
兩個方法設置進來的對象的preExecute
方法。在實際Activity啟動流程中,對應的是LaunchActivityItem
和ResumeActivityItem
兩個類的preExecute
方法。
TransactionExecutor
TransactionExecutor
是負責管理事務以正確的順序執(zhí)行的類。
public void execute(ClientTransaction transaction) { ... executeCallbacks(transaction); executeLifecycleState(transaction); mPendingActions.clear(); }
它首先會通過executeCallbacks
方法,執(zhí)行ClientTransaction
add的所有Callback的execute
和postExecute
方法,具體如下:
public void executeCallbacks(ClientTransaction transaction) { ... //獲取目標生命周期狀態(tài) final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest(); final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState() : UNDEFINED; // Index of the last callback that requests some post-execution state. final int lastCallbackRequestingState = lastCallbackRequestingState(transaction); final int size = callbacks.size(); for (int i = 0; i < size; ++i) { ... item.execute(mTransactionHandler, token, mPendingActions); item.postExecute(mTransactionHandler, token, mPendingActions); ... } }
讓我們回到Activity的啟動流程的代碼中,clientTransaction
加入了一個Callback————LaunchActivityItem
,從上文可以知,這個類的execute
方法里有這么一段代碼client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
,去負責啟動Activity。
executeLifecycleState方法
private void executeLifecycleState(ClientTransaction transaction) { final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest(); final IBinder token = transaction.getActivityToken(); final ActivityClientRecord r = mTransactionHandler.getActivityClient(token); if (r == null) { //第一次啟動獲得的r為null,實際上會走此分支,只有在performLaunchActivity方法調用后,r才不為null return; } // Cycle to the state right before the final requested state. cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction); // Execute the final transition with proper parameters. lifecycleItem.execute(mTransactionHandler, token, mPendingActions); lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions); }
我們重點關注一下cycleToPath
方法:
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState, ClientTransaction transaction) { final int start = r.getLifecycleState(); if (DEBUG_RESOLVER) { Slog.d(TAG, tId(transaction) + "Cycle activity: " + getShortActivityName(r.token, mTransactionHandler) + " from: " + getStateName(start) + " to: " + getStateName(finish) + " excludeLastState: " + excludeLastState); } final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState); performLifecycleSequence(r, path, transaction); }
mHelper.getLifecyclePath(start, finish, excludeLastState)
:根據(jù)當前Activity所處的狀態(tài)與目標生命周期狀態(tài),生成一個包含該狀態(tài)區(qū)間內所有狀態(tài)的Int數(shù)組。
private void performLifecycleSequence(ActivityClientRecord r, IntArray path, ClientTransaction transaction) { final int size = path.size(); for (int i = 0, state; i < size; i++) { state = path.get(i); if (DEBUG_RESOLVER) { Slog.d(TAG, tId(transaction) + "Transitioning activity: " + getShortActivityName(r.token, mTransactionHandler) + " to state: " + getStateName(state)); } switch (state) { case ON_CREATE: mTransactionHandler.handleLaunchActivity(r, mPendingActions, null /* customIntent */); break; case ON_START: mTransactionHandler.handleStartActivity(r, mPendingActions); break; case ON_RESUME: mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */, r.isForward, "LIFECYCLER_RESUME_ACTIVITY"); break; case ON_PAUSE: mTransactionHandler.handlePauseActivity(r.token, false /* finished */, false /* userLeaving */, 0 /* configChanges */, mPendingActions, "LIFECYCLER_PAUSE_ACTIVITY"); break; case ON_STOP: mTransactionHandler.handleStopActivity(r.token, false /* show */, 0 /* configChanges */, mPendingActions, false /* finalStateRequest */, "LIFECYCLER_STOP_ACTIVITY"); break; case ON_DESTROY: mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */, 0 /* configChanges */, false /* getNonConfigInstance */, "performLifecycleSequence. cycling to:" + path.get(size - 1)); break; case ON_RESTART: mTransactionHandler.performRestartActivity(r.token, false /* start */); break; default: throw new IllegalArgumentException("Unexpected lifecycle state: " + state); } } }
performLifecycleSequence
開始負責按順序執(zhí)行IntArray區(qū)間里的狀態(tài)變換。
讓我們重新回到Activity的啟動流程上,從handleLaunchActivity
繼續(xù)往下追蹤:
public Activity handleLaunchActivity(ActivityClientRecord r, ... final Activity a = performLaunchActivity(r, customIntent); ... }
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); //通過newInstance創(chuàng)建Activity實例 activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); if (activity != null) { CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); Window window = null; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; } appContext.setOuterContext(activity); //調用attach方法,開始初始化Activity activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback, r.assistToken); if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; checkAndBlockForNetworkAccess(); activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { //調用Activity的onCreate方法 mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } r.activity = activity; } r.setState(ON_CREATE); // updatePendingActivityConfiguration() reads from mActivities to update // ActivityClientRecord which runs in a different thread. Protect modifications to // mActivities to avoid race. synchronized (mResourcesManager) { mActivities.put(r.token, r); } } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); } } return activity; }
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
有些讀者可能會對這句話有些疑問,前面不是已經創(chuàng)建過Application對象了嗎,怎么這里還調用一遍,不是說一個進程里只能有一個Application對象嗎?
我們進入makeApplication
方法里看一下,第一句話就解釋了原因:
if (mApplication != null) { return mApplication; }
所以說,并不會重復創(chuàng)建,這里只是將之前已創(chuàng)建的Application重新獲取一下而已。
mInstrumentation.callActivityOnCreate(activity, r.state);
語句的調用,標識著Activity進入onCreate流程,接下來便是Ui的繪制與展示的流程,在此便不做展開分析了。
文章的最后,我們用一個簡單的圖表對這一篇activity的啟動流程做一個總結,并留給各位讀者一個面試中高頻次問題:請簡述一下Activity的啟動流程? 看看各位讀者能不能總結歸納出一個比較好的答案。
[ActivityThread.java] main() attach() | [ActivityManagerService.java] attachApplication() attachApplicationLocked() | | | [ActivityThread.java] | bindApplication() //發(fā)送了H.BIND_APPLICATION消息 | handleBindApplication() //創(chuàng)建Application實例,并調用onCreate方法 | | | [LoadedApk.java] | makeApplication() [ActivityTaskManagerService.java] attachApplication() | [RootActivityContainer.java] attachApplication() | [ActivityStackSupervisor.java] realStartActivityLocked() | [ClientLifecycleManager.java] scheduleTransaction() | [ClientTransaction.java] schedule() | [ActivityThread.java] executeTransaction() | [TransactionExecutor.java] execute() executeCallbacks() | [LaunchActivityItem.java] execute() | [ActivityThread.java] handleLaunchActivity() performLaunchActivity() //創(chuàng)建Activity實例,調用activity attach和onCreate方法
以上就是Android10 App啟動Activity源碼分析的詳細內容,更多關于Android10 App啟動的資料請關注腳本之家其它相關文章!
- Android registerForActivityResult動態(tài)申請權限案例詳解
- ActivityManagerService廣播并行發(fā)送與串行發(fā)送示例解析
- ActivityManagerService廣播注冊與發(fā)送示例解析
- ActivityManagerService之Service啟動過程解析
- Android面向單Activity開發(fā)示例解析
- Vue3源碼分析reactivity實現(xiàn)方法示例
- vue3源碼分析reactivity實現(xiàn)原理
- Android?Activity共享元素動畫示例解析
- Android?registerForActivityResult新用法實現(xiàn)兩個Activity間數(shù)據(jù)傳遞
相關文章
Android編程實現(xiàn)Gallery中每次滑動只顯示一頁的方法
這篇文章主要介紹了Android編程實現(xiàn)Gallery中每次滑動只顯示一頁的方法,涉及Android擴展Gallery控件實現(xiàn)翻頁效果控制的功能,涉及Android事件響應及屬性控制的相關技巧,需要的朋友可以參考下2015-11-11Jetpack Compose實現(xiàn)對話框和進度條實例解析
對話框和進度條其實并無多大聯(lián)系,放在一起寫是因為兩者的內容都不多,所以湊到一起,對話框是我們平時開發(fā)使用得比較多的組件,進度條的使用頻率也很高,比如下載文件,上傳文件,處理任務時都可以使用進度條2023-04-04Android開發(fā)筆記之:ListView刷新順序的問題詳解
本篇文章是對Android中ListView刷新順序的問題進行了詳細的分析介紹,需要的朋友參考下2013-05-05Android編程實現(xiàn)Toast只顯示最后一條的方法
這篇文章主要介紹了Android編程實現(xiàn)Toast只顯示最后一條的方法,結合實例形式總結了Toast只顯示最后一條的原理與具體實現(xiàn)技巧,需要的朋友可以參考下2017-08-08Android使用SQLite數(shù)據(jù)庫的簡單實例
這篇文章主要介紹了Android使用SQLite數(shù)據(jù)庫的簡單實例,有需要的朋友可以參考一下2013-12-12Andorid基于ZXing實現(xiàn)二維碼生成與掃描的示例代碼
ZXing是一個開源的條碼和二維碼掃描庫,它可以用于Android開發(fā)中,通過ZXing庫可以實現(xiàn)Android設備上的條碼和二維碼掃描功能,開發(fā)者可以輕松地在Android應用中集成條碼和二維碼掃描功能,本文主要給大家介紹了Andorid?ZXing實現(xiàn)二維碼,感興趣的朋友可以參考下2023-08-08