Android App啟動過程

renxhui發表於2019-09-03

概述

當你點選桌面App的圖示到底發生了什麼,上篇文章我們大概簡述了流程

  • App發起程式:如果從桌面啟動應用,則發起程式便是Launcher所在的程式,當從某App啟動遠端程式,則發起程式是App所在的程式,發起程式首先需要通過Binder傳送資訊給system_server程式
  • system_server程式:呼叫Process.start方法,通過SocketZygote程式傳送新建程式的請求
  • zygote程式:在執行ZygoteInit.main()後進入runSelectLoop()迴圈體,當有客戶端連線時,便會執行ZygoteConnection.runOnce()方法,再經過層層呼叫後fork出新的應用程式
  • 新程式:執行handleChildProc方法,設定程式名,開啟binder驅動,啟動新的binder執行緒,設定art虛擬機器引數,反射目標類的main方法,即呼叫ActivityThread.main()方法

這次我們來詳細的分析一下原始碼,基於API 27

1.Launcher

當你點選桌面上的App圖示,Launcher捕獲點選事件,其過程為Launcher#onClick-> Launcher#onClickAppShortcut->Launcher#startAppShortcutOrInfoActivity->Launcher#startActivitySafely -> Activity#startActivity最終呼叫了 startActivity(intent, optsBundle);方法

下面我們從startActivity(intent, optsBundle);方法開始分析呼叫流程

2.Activity.startActivity

上方我們說到了Activity.startActivity,點進原始碼發現呼叫的是Activity#startActivityForResult,其中還呼叫到了Instrumentation#execStartActivity這個方法,原始碼如下

  @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
    
     public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }
    
     public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    ...
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
    ...
    }
複製程式碼

3.Instrumentation.execStartActivity

Instrumentation.execStartActivity中,我們發現他呼叫了ActivityManager#getService()#startActivity,其中ActivityManager#getService()返回的是IActivityManager型別的Binder物件,他的具體實現在ActivityManagerService

  public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
    
    ActivityManager原始碼
      public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    
      private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
複製程式碼

4.ActivityManagerService.startActivity

我們檢視ActivityManagerService.startActivity原始碼,發現他呼叫了ActivityManagerService#startActivityAsUser,該方法又呼叫了ActivityStarter#startActivityMayWait原始碼如下

 public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    
     public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }
    
複製程式碼

5.ActivityStarter.startActivityMayWait

我們檢視ActivityStarter.startActivityMayWait原始碼發現他呼叫了ActivityStarter#startActivityLocked,接著是ActivityStarter#startActivity,然後是ActivityStarter#startActivityUnchecked,其中呼叫了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

final int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, Intent intent, String resolvedType,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, WaitResult outResult,
        Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
        TaskRecord inTask, String reason) {
    ...
    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor,
            resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
            reason);
    ...
}

int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
        ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
    ...
    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
            callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
            inTask);
}

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
        ActivityRecord[] outActivity, TaskRecord inTask) {
    ...
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
            options, inTask, outActivity);
}

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
    ...
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, doResume, options, inTask, outActivity);
    ...
}

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
    ...
    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
            mOptions);
    ...
}

複製程式碼

6.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

我們檢視ActivityStackSupervisor.resumeFocusedStackTopActivityLocked他呼叫了ActivityStack#resumeTopActivityUncheckedLocked,然後是ActivityStack#resumeTopActivityInnerLocked,接著又回到了ActivityStackSupervisor.java,呼叫了ActivityStackSupervisor#startSpecificActivityLocked,這個方法要判斷啟動的App程式是否存在,存在就直接啟動Activity,如果不存在就把程式建立出來

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    ...
    if (app != null && app.thread != null) {
        ...
        // 如果程式已存在,則通知程式啟動元件
        realStartActivityLocked(r, app, andResume, checkConfig);
        return;
        ...
    }
    // 否則先將程式建立出來
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
    ...
}
複製程式碼

7.mService.startProcessLocked

我們這裡分析程式不存在的情況,這裡的mService指的是ActivityManagerService,我們檢視ActivityManagerService#startProcessLocked原始碼如下

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    ...
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    startResult = Process.start(entryPoint,
            app.processName, uid, uid, gids, debugFlags, mountExternal,
            app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
            app.info.dataDir, invokeWith, entryPointArgs);
    ...
}
複製程式碼

最終呼叫Process.start來開啟新程式,這個程式的入口就會在android.app.ActivityThread.javamain方法,我們下面繼續分析ActivityThread#main

8.ActivityThread#main

ActivityThread#main方法其中呼叫了ActivityThread#attach方法,這個方法中的ActivityManager.getService()返回的是IActivityManager型別的Binder物件,其實現類是ActivityManagerService,原始碼如下

public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    ...
    Looper.loop();
    ...
}

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        ...
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            ...
        }
        ...
    }
    ...
}
複製程式碼

現在我們又回到了ActivityManagerService中,檢視其attachApplication方法,發現呼叫了thread#bindApplicationmStackSupervisor#attachApplicationLocked,我們一次講解這倆個方法作用

public final void attachApplication(IApplicationThread thread) {
    ...
    attachApplicationLocked(thread, callingPid);
    ...
}

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {
    ....
    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);
    ...
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            ...
        }
    }
    ...
}
複製程式碼

9.thread#bindApplication

上面說到的thread#bindApplication中的thread型別是ApplicationThread,是ActivityThread的一個內部類,繼承自IApplicationThread.Stub,我們檢視ApplicationThread#bindApplication方法,我發現呼叫了ActivityThread#sendMessage 方法,它內部呼叫mH.sendMessage來傳送訊息,其中mHActivityThread的一個內部類H的一個例項

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) {
    ...
    sendMessage(H.BIND_APPLICATION, data);
}

 void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }
    
   private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }
複製程式碼

10.H.handleMessage

我們來看一下H這個內部類的handleMessage,最終走到了ActivityThread#handleBindApplication方法

public void handleMessage(Message msg) {
    ...
    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;
        ...
    }
}

複製程式碼

11.ActivityThread#handleBindApplication

從原始碼中我們發現,他首先建立了mInstrumentation物件,呼叫data#info#makeApplication來建立Application物件,其中data#info代表的是LoadedApk的一個例項,檢視LoadedApk#makeApplication方法可以看到,內部呼叫了Instrumentation#newApplication方法,這個方法內部呼叫Class#newInstance()來完成對Application的例項化,然後呼叫Application#attach(context)來繫結Context

上面建立完Application後,就呼叫Instrumentation#callApplicationOnCreateApplicationonCreate生命週期,原始碼如下


private void handleBindApplication(AppBindData data) {
    ...
    final InstrumentationInfo ii;
    ...
    // 建立 mInstrumentation 例項
    if (ii != null) {
        final ApplicationInfo instrApp = new ApplicationInfo();
        ii.copyTo(instrApp);
        instrApp.initForUser(UserHandle.myUserId());
        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                appContext.getClassLoader(), false, true, false);
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

        try {
            final ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) {
            ...
        }
        ...
    } else {
        mInstrumentation = new Instrumentation();
    }
    ...
    Application app;
    ...
    // 建立 Application 例項
    try {
        ...
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    } finally {
        ...
    }
    ...
}



// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/LoadedApk.java#959
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        ...
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {// 傳入為 null 所以不走
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    }
    ...
    return app;
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/Instrumentation.java#1084
  public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }
    
 static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }
複製程式碼

12.mStackSupervisor#attachApplicationLocked

上面說完了thread#bindApplication這個方法,下面我們繼續說mStackSupervisor#attachApplicationLocked這個方法,其mStackSupervisorActivityStackSupervisor的一個例項,我們檢視ActivityStackSupervisor#attachApplicationLocked方法發現其中呼叫了ActivityStackSupervisor#realStartActivityLocked,這個方法呼叫了app#thread#scheduleLaunchActivity,原始碼如下

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#956
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    ...
    if (realStartActivityLocked(activity, app,
            top == activity /* andResume */, true /* checkConfig */)) {
        ...
    }
    ...
}


// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#1313
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
            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, app.repProcState, r.icicle,
            r.persistentState, results, newIntents, !andResume,
            mService.isNextTransitionForward(), profilerInfo);
    ...
}
複製程式碼

12.app#thread#scheduleLaunchActivity

上面說到app#thread#scheduleLaunchActivity,這個裡面的threadIApplicationThread,他的實現類是ActivityThread#ApplicationThread,我們檢視ActivityThread#ApplicationThread#scheduleLaunchActivity方法中的程式碼,發現最終是傳送了LAUNCH_ACTIVITY的訊息,傳送訊息我們再9 ,10步驟中分析過,我們直接檢視處理訊息的程式碼,在 H#handleMessage方法中,我們可以看到他會接收並處理很多四大元件的相關操作,我們檢視 LAUNCH_ACTIVITY的處理,發現其處理方法是呼叫了ActivityThread#handleLaunchActivity,這個方法再次涉及到了Instrumentation類,之前建立Application的時候用到了他,如今建立Activity也用到了他,其中Instrumentation#newActivity是通過 Class.newInstance()來例項化Activity,例項化完成後回到ActivityThread#performLaunchActivity中,讓Activity依附到window中,然後callActivityOnCreate走ActivityonCreate的生命週期,涉及到的原始碼如下

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#756
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
        int procState, Bundle state, PersistableBundle persistentState,
        List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#1580
public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
        ...
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        ...
    }
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2833
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
    ...
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2644
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        ...
    }

    try {
        // 返回之前建立過的 application 物件
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
        if (activity != null) {
            ...
            // attach 到 window 上
            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);
            ...
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
        }
    } catch (Exception e) {
        ...
    }
    return activity;
}

  public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

複製程式碼

總結

概述一下大致流程

  • 首先是點選App圖示,此時是執行在Launcher程式,通過ActivityManagerServiceBinder IPC的形式向system_server程式發起startActivity的請求
  • system_server程式接收到請求後,通過Process.start方法向zygote程式傳送建立程式的請求
  • zygote程式fork出新的子程式,即App程式
  • 然後進入ActivityThread.main方法中,這時執行在App程式中,通過ActivityManagerServiceBinder IPC的形式向system_server程式發起attachApplication請求
  • system_server接收到請求後,進行一些列準備工作後,再通過Binder IPC向App程式傳送scheduleLaunchActivity請求
  • App程式binder執行緒(ApplicationThread)收到請求後,通過Handler向主執行緒傳送LAUNCH_ACTIVITY訊息
  • 主執行緒收到Message後,通過反射機制建立目標Activity,並回撥ActivityonCreate

Android App啟動過程

參考:gityuan.com/2016/03/12/…

blankj.com/2018/09/29/…

juejin.im/entry/58610…

相關文章