Android應用程式啟動源碼淺析-(三萬字長文慎點&Android14)

来源:https://www.cnblogs.com/anywherego/p/18233682
-Advertisement-
Play Games

在Android桌面Launcher源碼淺析中介紹了Android的桌面程式Launcher是如何響應用戶點擊事件並啟動App的,這篇文章繼續介紹App在Android系統層的啟動流程。 一、啟動流程 sequenceDiagram participant User participant Laun ...


Android桌面Launcher源碼淺析中介紹了Android的桌面程式Launcher是如何響應用戶點擊事件並啟動App的,這篇文章繼續介紹App在Android系統層的啟動流程。

一、啟動流程

sequenceDiagram participant User participant Launcher participant ActivityManagerService participant Zygote participant AppProcess participant Application participant FirstActivity User ->> Launcher: 點擊應用圖標 Launcher ->> ActivityManagerService: 請求啟動Activity ActivityManagerService ->> Zygote: 創建新進程 Zygote -->> AppProcess: fork新進程 AppProcess ->> Application: 創建Application實例 Application ->> FirstActivity: 啟動第一個Activity FirstActivity ->> User: 顯示界面

二、Launcher通知AndroidOS(用戶點擊圖標)

2.1 Activity.java

frameworks/base/core/java/android/app/Activity.java 源碼地址

  • Android桌面Launcher源碼淺析中提到Launcher最終通過frameworks/base/core/java/android/app/Activity.java中的startActivity方法啟動了對應的應用程式。
  • startActivity方法是通過調用startActivityForResult方法來實現的。
  • startActivityForResult方法最終調用了/frameworks/base/core/java/android/app/Instrumentation.javaexecStartActivity方法
public class Activity {

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }
    
    @Override
    public void startActivityForResult(...) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            // 調用Instrumentation的execStartActivity方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(...);
        }
    }

}

2.2 Instrumentation.java

frameworks/base/core/java/android/app/Instrumentation.java 源碼地址

  • Instrumentation.java中的execStartActivity方法是Activity啟動流程的關鍵。
  • execStartActivity方法通過ActivityTaskManager.getService().startActivity方法與系統服務進行通信.
// Instrumentation中有多個execStartActivity同名方法,註意是target的類型為Activity的方法
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
        
        // ActivityTaskManager.getService()獲取到ActivityTaskManagerService的實例對象
        // 調用ActivityTaskManagerService.startActivity
        int result = ActivityTaskManager.getService()
                .startActivity(...);
}

2.3 ActivityTaskManagerService.java

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java 源碼地址

  • ActivityTaskManagerService是一個系統服務,負責管理Activity的啟動。
  • startActivity方法調用了startActivityAsUser方法
  • startActivityAsUser方法通過ActivityStartControllerobtainStarter方法獲取了ActivityStarter對象實例,並調用ActivityStarterexecute方法
public final int startActivity(...) {
    // 調用startActivityAsUser方法
    return startActivityAsUser(...);
}

public final int startActivityAsUser(...) {

    // ActivityStartController的obtainStarter獲取了ActivityStarter對象
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                ... // 構造參數
                .execute();
}

2.4 ActivityStarter.java

/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java 源碼地址

  • ActivityStarter中最終會調用RootWindowContainerresumeFocusedTasksTopActivities方法
int execute() {
    // 調用executeRequest方法
    res = executeRequest(mRequest);
}

private int executeRequest(Request request) {
    // 創建ActivityRecord對象
    final ActivityRecord r = new ActivityRecord.Builder(mService)
            .setCaller(callerApp)
            ... // 構造參數
            .build();
    // 調用startActivityUnchecked方法
    mLastStartActivityResult = startActivityUnchecked(...);
}

private int startActivityUnchecked(...) {
    // 調用startActivityInner
    result = startActivityInner(...);
}

int startActivityInner(...) {
    // 調用RootWindowContainer的resumeFocusedTasksTopActivities方法
    mRootWindowContainer.resumeFocusedTasksTopActivities(...);
}

2.5 RootWindowContainer.java

/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java 源碼地址

  • RootWindowContainer是WindowManagerService的主要組成部分之一,是一個管理視窗的容器。
  • 調用TaskTaskFragment將前臺程式Pause,為新的應用程式啟動做準備。
  • resumeFocusedTasksTopActivities中調用TaskresumeTopActivityUncheckedLocked方法。

private boolean resumeFocusedTasksTopActivities(...) {
    // 調用Task的resumeTopActivityUncheckedLocked方法
    result = targetRootTask.resumeTopActivityUncheckedLocked(...);
}

2.5.1 Task.java

/frameworks/base/services/core/java/com/android/server/wm/Task.java 源碼地址

  • Task最終調用TaskFragmentresumeTopActivity方法
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(...) {
    // 調用resumeTopActivityInnerLocked
    someActivityResumed = resumeTopActivityInnerLocked(...);
}

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(...) {
    final TaskFragment topFragment = topActivity.getTaskFragment();
    // 調用TaskFragment的resumeTopActivity
    resumed[0] = topFragment.resumeTopActivity(...););
    return resumed[0];
}

2.5.2 TaskFragment.java

/frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java 源碼地址

  • TaskFragment最終調用ActivityTaskManagerServicestartProcessAsync方法
final boolean resumeTopActivity(...) {
   // 暫停當前視窗的Aciticity,可參見源碼
   ...
   // 調用ActivityTaskManagerService的startProcessAsync方法創建新的Activity
ActivityTaskManagerService的startProcessAsync方法
   mAtmService.startProcessAsync(...);
}

2.6 再次回到ActivityTaskManagerService.java

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java 源碼地址

  • 處理完視窗容器數據以後(核心工作是將前臺程式Pause),再次回到了ActivityTaskManagerService
  • startProcessAsync方法發送非同步消息,調用ActivityManagerInternalstartProcess方法
  • ActivityManagerInternal的實現類是ActivityManagerService
// mAmInternal的獲取方法,註冊方法在ActivityManagerService中(下一小節2.8做介紹)
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);

void startProcessAsync(...) {
    
        // PooledLambda會自動調用mAmInternal(ActivityManagerInternal)的startProcess方法
        final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess, mAmInternal, ...);
        mH.sendMessage(m);
}
  • ActivityManagerInternal是一個抽象類,具體實現在ActivityManagerService.java中實現

2.7 ActivityManagerService.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 源碼地址

  • ActivityManagerService最終調用ProcessListstartProcessLocked方法
public class ActivityManagerService extends IActivityManager.Stub {
    
    // 初始化LocalService(ActivityManagerInternal)
    private final ActivityManagerInternal mInternal = new LocalService();

    public void init() {
        // 在LocalServices中進行註冊
        LocalServices.addService(ActivityManagerInternal.class, mInternal);
    }
    private class LocalService extends ActivityManagerInternal {
        // ActivityManagerInternal 介面方法的具體實現
        @Override
        public void startProcess(...) {
            synchronized (ActivityManagerService.this) {
                // 調用ActivityManagerService的startProcessLocked方法
                startProcessLocked(...)
            }
        }
    }
        @GuardedBy("this")
    final ProcessRecord startProcessLocked(...) {
        // 調用ProcessList的startProcessLocked
        return mProcessList.startProcessLocked(...);
    }
}

2.7.1 ProcessList.java

/frameworks/base/services/core/java/com/android/server/am/ProcessList.java 源碼地址

  • ProcessList最終調用到ZygoteProcessstart方法
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, ...) {
    // 定義創建Activity完成後回調的入口點(重要)
    final String entryPoint = "android.app.ActivityThread";
    return startProcessLocked(hostingRecord, ...);
}

@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord, ...) {
    // 調用startProcess
    final Process.ProcessStartResult startResult = startProcess(...);
}

private Process.ProcessStartResult startProcess(...) {
    // 獲取AppZygote
    final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
    // appZygote.getProcess()獲取到ChildZygoteProcess類(ZygoteProcess的子類)
    // 調用ZygoteProcess的start方法
    startResult = appZygote.getProcess().start(entryPoint,...);
}

2.8 ZygoteProcess.java

/frameworks/base/core/java/android/os/ZygoteProcess.java 源碼地址

  • ZygoteProcess發送消息給Zygote進程,通過Zygote進程創建新的activity進程
public final Process.ProcessStartResult start(...) {
    // 調用startViaZygote
    return startViaZygote(...)
}

private Process.ProcessStartResult startViaZygote(...) {
    // 通過openZygoteSocketIfNeeded(abi)打開一個到Zygote進程的套接字連接(Socket)。
    // 調用zygoteSendArgsAndGetResult
    return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),zygotePolicyFlags,argsForZygote);
}

@GuardedBy("mLock")
private Process.ProcessStartResult zygoteSendArgsAndGetResult(...) {
    // 調用attemptZygoteSendArgsAndGetResult
    return attemptZygoteSendArgsAndGetResult(...);
}

private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(...) {
    try {
        // 創建Zygote套接字的輸入輸出流
        final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
        final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

        // 發送消息給 Zygote 進程
        zygoteWriter.write(msgStr);
        zygoteWriter.flush();

        // 讀取 Zygote 進程返回的結果
        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = zygoteInputStream.readInt();
        result.usingWrapper = zygoteInputStream.readBoolean();
        // 檢查 PID 是否有效
        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }

        return result;
    } catch (IOException ex) {
        zygoteState.close();
        Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
                + ex.toString());
        throw new ZygoteStartFailedEx(ex);
    }
}

三、Activity進程創建(Zygote進程fork)

Android啟動過程-萬字長文(Android14)介紹了Zygote進程(孵化器進程)

3.1 Zygote簡介

  • Zygote進程是一個用戶進程,由init進程(1號進程)fork而來。
  • Zygote進程通過fork的方式創建新的應用程式進程。
  • Zygote進程的入口點是ZygoteInit類中的main方法。

下麵將簡單介紹在Zygote進程的代碼流轉。

3.2 ZygoteInit.java

Android14的ZygoteInit源碼地址

  • Zygote進程是在Android系統啟動過程中創建的,創建完成後會通過ZygoteServer來監聽消息
public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();
    ...

    // 啟動Zygote伺服器,迴圈監聽消息
    caller = zygoteServer.runSelectLoop(abiList);
    if (caller != null) {
        // 有新的消息就執行對應Runnable代碼
        caller.run();
    }
    ...
}

3.3 ZygoteServer.java

Android14的ZygoteServer源碼地址

  • ZygoteServer獲取到消息後會調用ZygoteConnectionprocessCommand方法
Runnable runSelectLoop(String abiList) {

    while (true) {
        // 使用 select 監聽套接字
        StructPollfd[] pollFDs = new StructPollfd[socketFDs.size()];
        
        if (pollIndex == 0) {
            // 接收到新的連接
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            peers.add(newPeer);
            socketFDs.add(newPeer.getFileDescriptor());
        } else {
            // 處理已有連接的請求
            ZygoteConnection connection = peers.get(pollIndex);
            final Runnable command = connection.processCommand(this, multipleForksOK);
        }
    }
}

3.4 ZygoteConnection.java

Android14的ZygoteConnection源碼地址

  • ZygoteConnectionprocessCommand方法最終調用ZygoteInitzygoteInit方法

Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
    ...
    // 調用Zygote的forkAndSpecialize方法fork出Acitivity的進程
    pid = Zygote.forkAndSpecialize(...);
    
    if (pid == 0) {
        // 在子進程中,即創建出來的應用程式所在進程
        return handleChildProc(parsedArgs, childPipeFd,
                parsedArgs.mStartChildZygote);
    } else {
        // 在父線程中,pid為創建好的子進程的id
        handleParentProc(pid, serverPipeFd);
        return null;
    }
}

private void handleParentProc(int pid, FileDescriptor serverPipeFd) {
    // 通過套接字Socket將子進程的 PID 返回給請求方(ActivityManagerService)
    os.writeInt(pid);
}


private Runnable handleChildProc(...) {
    
        // 子進程負責應用程式後續的初始化工作
        ZygoteInit.zygoteInit(...)
}

  • fork系統調用會創建一個新的進程(子進程)。在調用fork後,父進程和子進程(新創建出來的進程)會各自執行後續的代碼。
  • 在父進程中,fork返回子進程的PID。這是一個正整數,表示新創建的子進程的進程ID。
  • 在子進程中(新進程),fork 返回 0。這表示當前進程是新創建的子進程。
  • 應用程式(App)的進程就是新創建的子進程

3.5 再次回到ZygoteInit.java

Android14的ZygoteInit源碼地址

  • 調用RuntimeInit.applicationInit方法,進行應用程式的初始化過程
public static Runnable zygoteInit(...) {
    // 常見的初始化工作,例如設置系統屬性、初始化預設的未捕獲異常處理器等
    RuntimeInit.commonInit();
    // Zygote相關的初始化工作。這個初始化過程在C/C++層面進行,設置了必要的Zygote運行環境
    ZygoteInit.nativeZygoteInit();
    // 調用RuntimeInit.applicationInit方法,進行應用程式的初始化過程
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader);
}

3.6 RuntimeInit.java

Android14的RuntimeInit源碼地址

  • RuntimeInitapplicationInit方法完成初始化工作後,通過反射的方式,調用android.app.ActivityThreadmain方法
  • 參數列表中的startClass2.9 ProcessList.java源碼中的entryPoint(android.app.ActivityThread)
protected static Runnable applicationInit(...) {
    // 查找並返回應用程式的主方法
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

private static Runnable findStaticMain(...) {
    // 反射得到android.app.ActivityThread類
    cl = Class.forName(className, true, classLoader);
    // 反射獲取main方法
    m = cl.getMethod("main", new Class[] { String[].class });
    // 返回可被執行的Runnable對象
	return new MethodAndArgsCaller(m, argv);
}

四、初始化Application實例

通過Zygote進程fork出應用程式的進程後,下一步就是創建整個應用程式的Application實例

4.1 ActivityThread.java

Android14的ActivityThread源碼地址

  • 創建應用程式的ActivityThread實例
  • 創建應用程式的Application實例
  • 創建應用程式的Looper迴圈
public static void main(String[] args) {

    // 初始化主線模塊
    initializeMainlineModules();
    // 創建MainLooper
    Looper.prepareMainLooper();
    // 創建ActivityThread
    ActivityThread thread = new ActivityThread();
    // 創建應用程式Application實例
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    // 迴圈監聽消息
    Looper.loop();
}

@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
    // 獲取ActivityManagerService實例
    final IActivityManager mgr = ActivityManager.getService();
    // 調用ActivityManagerService的attachApplication方法
    mgr.attachApplication(mAppThread, startSeq);
}

4.2 ActivityManagerService.java

Android14的ActivityManagerService源碼地址

  • ActivityManagerService完成Application創建和第一個Activity的創建
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    // 調用attachApplicationLocked方法
    attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}

private void attachApplicationLocked(...) {
    // 調用ActivityThread的bindApplication方法創建並綁定Application
    thread.bindApplication(...)
    // 在結束Application創建後調用finishAttachApplicationInner啟動app的第一個Activity頁面,在4.5會介紹這一部分代碼
    finishAttachApplicationInner(startSeq, callingUid, pid);
}

4.3 再次回到ActivityThread.java

Android14的ActivityThread源碼地址

  • 通過Handler機制完成消息的傳遞,正式載入apk文件
public final void bindApplication(...) {
    AppBindData data = new AppBindData();
    ... // 構造data的數據
    // H為Handler, BIND_APPLICATION是int值
    
    sendMessage(H.BIND_APPLICATION, data);
}

// ActivityThread的內部類H
class H extends Handler {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case BIND_APPLICATION:
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                break;
        }
    }
}

@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
    Application app;
    // 最終調用LoadedApk的makeApplicationInner方法載入apk文件到記憶體中
    app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
    // 調用Application的onCreate方法,正式進入apk執行文件
    mInstrumentation.callApplicationOnCreate(app);
}

4.4 LoadedApk.java

Android14的LoadedApk源碼地址

private Application makeApplicationInner(...) {
    // 獲取app的application類(在AndroidManifast.xml中定義的),沒有就使用預設的android.app.Application
    String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
            myProcessName);
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }
    // 調用Instrumentation的newApplication方法創建Application對象
    app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
}

4.5 Instrumentation.java

Android14的Instrumentation源碼地址

  • Instrumentation完成Application實例的初始化,並調用onCreate方法
// 創建Application對象
static public Application newApplication(Class<?> clazz, Context context) {
    // Application實例的初始化
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
}

// 調用Application的onCreate方法
public void callApplicationOnCreate(Application app) {
    app.onCreate();
}

五、啟動第一個Activity

5.1 ActivityManagerService.java

Android14的ActivityManagerService源碼地址

  • 在執行完Application的onCreate方法後,我們再回到ActivityManagerService.javaattachApplicationLocked方法中
  • attachApplicationLocked方法最終會調用LocalServiceattachApplication方法來載入我們的第一個Acitivity頁面
  • ActivityTaskManagerInternal是定義在ActivityTaskManagerService.javaLocalService
private void attachApplicationLocked(...) {
    // 調用ActivityThread的bindApplication方法創建並綁定Application
    thread.bindApplication(...)
    // 在結束Application創建後調用finishAttachApplicationInner啟動app的第一個Activity頁面
    finishAttachApplicationInner(startSeq, callingUid, pid);
}

private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
    if (normalMode) {
        try {
        // 調用`ActivityTaskManagerInternal`(即ActivityTaskManagerService.LocalService)的**attachApplication**方法來載入我們的第一個Acitivity頁面
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        }
    }
}

5.2 ActivityTaskManagerService.java

Android14的ActivityTaskManagerService源碼地址

  • 在LocalService中調用RootWindowContainer.attachApplication方法
final class LocalService extends ActivityTaskManagerInternal {
    @Override
    public boolean attachApplication(WindowProcessController wpc){
        // 調用RootWindowContainer的attachApplication
        return mRootWindowContainer.attachApplication(wpc);
    }
}

5.3 RootWindowContainer.java

Android14的RootWindowContainer源碼地址

  • 最終調用ActivityTaskSupervisorrealStartActivityLocked方法
boolean attachApplication(WindowProcessController app) throws RemoteException {
    // 調用RootWindowContainer內部類AttachApplicationHelper的process方法
    return mAttachApplicationHelper.process(app);
}
private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
    boolean process(WindowProcessController app) throws RemoteException {
        mApp = app;
        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            // 通過/frameworks/base/services/core/java/com/android/server/wm/Task.java中的forAllRootTasks調用test方法
            getChildAt(displayNdx).forAllRootTasks(this);
        }
    }
    
    public boolean test(ActivityRecord r) {
        // 調用ActivityTaskSupervisor的realStartActivityLocked方法
        mTaskSupervisor.realStartActivityLocked(...)
    }
}

5.3.1 Task.java

/frameworks/base/services/core/java/com/android/server/wm/Task.java源碼地址

boolean forAllRootTasks(Predicate<Task> callback, boolean traverseTopToBottom) {
    // 調用test方法
    return isRootTask() ? callback.test(this) : false;
}

5.4 ActivityTaskSupervisor.java

Android14的ActivityTaskSupervisor源碼地址

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        // 創建ClientTransaction啟動事務:
        final ClientTransaction clientTransaction = ClientTransaction.obtain(
                proc.getThread(), r.token);
        ...
        // 添加LaunchActivityItem回調
        clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent...));
        ...
        // 執行啟動事務,調用ClientLifecycleManager的scheduleTransaction方法
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);
        ...

}

  • ClientTransaction事務對象,用於描述一系列客戶端(即應用進程)需要執行的操作。
  • LaunchActivityItem回調參數中包括如何啟動Activity,啟動所需的Intent、配置、狀態等信息。

5.4.1 ClientLifecycleManager.java

Android14的ClientLifecycleManager源碼地址

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    // 調用ClientTransaction的schedule
    transaction.schedule();
}

5.4.2 ClientTransaction.java

Android14的ClientTransaction源碼地址

public void schedule() throws RemoteException {
    // 調用mClient的scheduleTransaction方法
    mClient.scheduleTransaction(this);
}
  • mClientIApplicationThread介面,實際是ActivityThread的內部類ApplicationThread對象。
  • mClientActivityTaskSupervisor的realStartActivityLocked方法中通過ClientTransaction.obtain(proc.getThread(), r.token),具體可參考ActivityTaskSupervisor源碼

5.5 回到ActivityThread.java

Android14的ActivityThread源碼地址

private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        // 調用ActivityThread的scheduleTransaction
        ActivityThread.this.scheduleTransaction(transaction);
    }
}
  • scheduleTransaction方法實際調用的是ActivityThread父類ClientTransactionHandlerscheduleTransaction方法

5.5.1 ClientTransactionHandler.java

Android14的ClientTransactionHandler源碼地址

void scheduleTransaction(ClientTransaction transaction) {
   transaction.preExecute(this);
   // 將事務放入消息隊列中,等待主線程的處理
   sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

5.5.2 ActivityThread的內部Handler類H處理消息

Android14的ActivityThread源碼地址

public void handleMessage(Message msg) {
    switch (msg.what) {
        case EXECUTE_TRANSACTION:
            final ClientTransaction transaction = (ClientTransaction) msg.obj;
            mTransactionExecutor.execute(transaction);
            break;
    }
}

5.5.3 TransactionExecutor.java

Android14的TransactionExecutor源碼地址

public void execute(ClientTransaction transaction) {
    // 執行事務中的回調和生命周期狀態請求
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
}

public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    // 遍歷事務中的所有回調項,並調用每個回調項的execute方法。
    for (int i = 0, size = callbacks.size(); i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        item.execute(mClient, mTransactionHandler, transaction.getLifecycleStateRequest());
    }
}
  • 每個回調項的execute方法實際就是調用LaunchActivityItemexecute方法

5.5.4 LaunchActivityItem.java

Android14的LaunchActivityItem源碼地址

@Override
public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
    client.handleLaunchActivity(new LaunchActivityItem.ActivityClientRecord(this), pendingActions, null);
}
  • 調用ClientTransactionHandler即ActivityThreadhandleLaunchActivity方法

5.6 回到ActivityThread

Android14的ActivityThread源碼地址

public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {
    // 調用performLaunchActivity
    final Activity a = performLaunchActivity(r, customIntent);
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 創建activity對象
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
}

5.6.1 Instrumentation.java

Android14的Instrumentation源碼地址

public Activity newActivity(...) {
    // 創建Activity
    Activity activity = (Activity)clazz.newInstance();
    ...
    return activity;
}

5.6.2 回到ActivityThread的performLaunchActivity方法

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 創建activity對象
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    // activity綁定上下文Context
    activity.attach(appContext, this, getInstrumentation(), r.token,...);
    // 調用Instrumentation的callActivityOnCreate方法
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
}

5.6.3 Instrumentation的callActivityOnCreate方法

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    // 調用Activity的performCreate方法
    activity.performCreate(icicle);
}

5.7 Activity.java

Android14的Activity源碼地址

  • 在Activity中實現了生命周期方法的調用邏輯

5.7.1 onCreate方法

final void performCreate(...) {
    // 調用onCreate方法
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
}
  • 繞了一大圈,最終又回到了Activity.java
  • 在performCreate中調用onCreate生命周期方法

5.7.2 onStart方法

5.7.2.1 TransactionExecutor.java

  • TransactionExecutor.java的方法execute中通過executeCallbacks創建了Activity並調用onCreate方法
  • 然後在executeLifecycleState方法中調用後續的生命周期方法
public void execute(ClientTransaction transaction) {
    // 執行事務中的回調
    executeCallbacks(transaction);
    // 執行生命周期
    executeLifecycleState(transaction);
}

public void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem != null) {
        // 調用ActivityLifecycleItem的execute方法
        lifecycleItem.execute(transaction.getClientTransactionHandler(), token, pendingActions);
    }
}

  • ActivityResultItem是一個抽象類
  • 這裡實際調用的是ActivityResultItemexecute方法

5.7.2.2 ActivityResultItem.java

Android14的ActivityResultItem源碼地址

public void execute(ClientTransactionHandler client, IBinder token,
                    PendingTransactionActions pendingActions) {
    client.handleResumeActivity(token, true /* isForward */, "RESUME_ACTIVITY");
}
  • 這裡實際調用的是ActivityThreadhandleResumeActivity方法

5.7.2.3 ActivityThread的handleResumeActivity方法

Android14的ActivityThread源碼地址

public void handleResumeActivity(IBinder token, boolean finalStateRequest, String reason) {
    // 先調用ActivityThread的performStart方法
    performRestartActivity(r);
    // 再調用Activity的performResume
    r.activity.performResume();
}

public void performRestartActivity(ActivityClientRecord r) {
    // 調用Activity的performStart
    r.activity.performStart();
}


5.7.2.4 Activity的performStart方法

Android14的Activity源碼地址

final void performStart() {
    // 調用Instrumentation的callActivityOnStart方法
    mInstrumentation.callActivityOnStart(this);
}

5.7.2.5 Instrumentation的callActivityOnStart方法

Android14的Instrumentation源碼地址

public void callActivityOnStart(Activity activity) {
    activity.onStart();
}

5.7.3 onResume方法

5.7.2.3 ActivityThread的handleResumeActivity方法中提到在onStart方法執行後會調用r.activity.performResume();Activity的performResume方法

5.7.3.1 Activity的performResume方法

Android14的Activity源碼地址

final void performResume(boolean followedByPause, String reason) {
    mInstrumentation.callActivityOnResume(this);
}

5.7.3.2 Instrumentation的callActivityOnResume方法

Android14的Instrumentation源碼地址

public void callActivityOnResume(Activity activity) {
    activity.onResume();
}
  • 至此Activity創建完成,並完成了核心生命周期方法的創建
  • 在onResume方法後,Activity進入前臺,準備顯示給用戶

六、 後續工作

在生命周期完成後,應用程式就會被展示在屏幕上,後續的工作主要是渲染,這裡做一個簡單的流程說明

  • Activity實例化時創建一個Window對象,預設情況下是PhoneWindow。在PhoneWindow中,有一個 DecorView,它是整個視圖層次的根視圖。
  • 在Activity的onCreate方法中,Activity會調用setContentView方法,將佈局資源載入到DecorView中
  • WindowManager負責管理應用程式視窗,將DecorView添加到視窗中
  • 當DecorView被添加到視窗中後。ViewRootImpl類負責視圖層次結構的測量(measure)、佈局(layout)和繪製(draw)
  • 最終由SurfaceFlinger合成並顯示在屏幕上

以上就是應用程式啟動的全過程,如有錯漏,歡迎留言討論。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在MySQL InnoDB Cluster中,有一個系統變數/參數group_replication_transaction_size_limit控制著事務的大小,如下所示 mysql> select @@global.group_replication_transaction_size_limit ...
  • 軟體版本 Redis 7.2.5 Docker 26.1.3 準備工作 由於docker直接拉取運行了,所以需要提前準備配置文件 Index of /releases/ (redis.io) 下載後,把redis-7.2.5.tar.gz\redis-7.2.5.tar\redis-7.2.5\里的 ...
  • 各位熱愛 DolphinScheduler 的小伙伴們,社區5月份月報更新啦!這裡將記錄 DolphinScheduler 社區每月的重要更新,歡迎關註,期待下個月你也登上Merge Star月度榜單哦~ 月度Merge Star 感謝以下小伙伴5月份為 Apache DolphinSchedule ...
  • 各位熱愛 SeaTunnel 的小伙伴們,社區 5 月份月報來啦! SeaTunnel 正在迅猛發展,積極投入社區項目建設的小伙伴將促進SeaTunnel不斷提升數據同步的高可擴展性、高性能及高可靠性。歡迎關註每月月報更新,期待在下個月的Merge Star月度榜單看到你的身影哦~ SeaTunne ...
  • 本文分享自華為雲社區《DTSE Tech Talk × openGemini :從資料庫設計到性能調優,全面掌握openGemini應用開發最佳實踐》,作者:華為雲開源。 在本期《從資料庫設計到性能調優,全面掌握openGemini應用開發最佳實踐》的主題直播中,華為雲開源DTSE技術佈道師&ope ...
  • 本文分享自華為雲社區《【華為雲MySQL技術專欄】MySQL記憶體增長問題分析案例》,作者:GaussDB 資料庫。 前言 在現網環境中,偶爾會遇到客戶實例記憶體OOM(Out Of Memory,即記憶體耗盡或溢出)的情況。MySQL資料庫作為一款面向高併發應用場景的系統軟體,因其應用場景複雜且函數調用 ...
  • 前言 數據傳輸的數據格式有以下幾種常見的格式: JSON(JavaScript Object Notation):JSON是一種輕量級的數據交換格式,可讀性高且易於解析。它使用鍵值對的方式表示數據,並且支持多層嵌套。 XML(eXtensible Markup Language):XML是一種標 ...
  • 一、背景信息 早幾年買的小米盒子3增強版,放在家裡也沒怎麼用,娃最近總要看動畫片,網上去找一些軟體裝上了,但速度很慢,遙控器按下去要等個幾秒才能響應,系統里還到處都是廣告,就想著能不能刷下。 具體配置如下: 型號:小米盒子3增強版 (MDZ-18-AA) 安卓版本:5.2 小米版本:1.5.93 內 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...