Android第一個繪製的Surface

語言: CN / TW / HK

如何監控冷啟動

一旦系統建立了應用程式程序,應用程式程序就負責接下來的階段:

  1. 建立應用程式物件。

  2. 啟動主執行緒。

  3. 建立主要 Activity 。

  4. 填充 View 。

  5. 佈置螢幕。

  6. 進行初始化繪製。

一旦應用程序完成了第一次繪製,系統程序就會換出當前顯示的背景視窗,用主活動替換它。 此時,使用者可以開始使用該應用程式。

主執行緒開始

在上一篇博文中,我們瞭解到:

當應用程式程序啟動時,它會呼叫 ActivityThread.main(),它會在 system_server 程序中對 ActivityManagerService.attachApplication() 進行阻塞 IPC 呼叫。

system_server 程序對應用程序中的 ActivityThread.bindApplication() 進行 IPC 呼叫,這將 BIND_APPLICATION 訊息排入主執行緒訊息佇列。

當對 ActivityManagerService.attachApplication() 的 IPC 呼叫完成後,ActivityThread.main() 然後呼叫 Looper.loop(),它會永遠迴圈,處理髮布到其 MessageQueue 的訊息。

處理的第一條訊息是 BIND_APPLICATION,它呼叫 ActivityThread.handleBindApplication() 來載入 APK 並載入應用程式元件。

這裡重要的一點是,在對 ActivityManagerService.attachApplication() 的 IPC 呼叫返回之前,應用程式程序主執行緒中不會發生任何事情。

排程 Activity 啟動

來看看呼叫ActivityThread.bindApplication()後system_server程序發生了什麼: ``` public class ActivityManagerService extends IActivityManager.Stub {

private boolean attachApplicationLocked( IApplicationThread thread, int pid, int callingUid, long startSeq) { thread.bindApplication(...);

// See if the top visible activity is waiting to run
//  in this process...
mAtmInternal.attachApplication(...);

// Find any services that should be running in this process...
mServices.attachApplicationLocked(app, processName);

// Check if a next-broadcast receiver is in this process...
if (isPendingBroadcastProcessLocked(pid)) {
    sendPendingBroadcastsLocked(app);
}
return true;

} } ```

與 Activity 啟動相關的行是 mAtmInternal.attachApplication(...)。 它呼叫 ActivityTaskManagerService.attachApplication() 呼叫 RootActivityContainer.attachApplication: ``` class RootActivityContainer extends ConfigurationContainer {

boolean attachApplication(WindowProcessController app) { for (ActivityDisplay display : mActivityDisplays) { ActivityStack stack = display.getFocusedStack() ActivityRecord top = stack.topRunningActivityLocked(); stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList); for (ActivityRecord activity : mTmpActivityList) { if (activity.app == null && app.mUid == activity.info.applicationInfo.uid && app.mName.equals(activity.processName)) { mStackSupervisor.realStartActivityLocked( activity, app, top == activity / andResume /, true / checkConfig / ) } } } ... } } ```

上面的程式碼:

迭代每個 Display 。

檢索該 Display 的焦點 Activity 堆疊。

迭代焦點 Activity 堆疊的每個 Activity 。

如果該 Activity 屬於正在啟動的程序,則呼叫 ActivityStackSupervisor.realStartActivityLocked()。 請注意,如果活動位於堆疊頂部,則傳遞為 true 的 andResume 引數。

這是 ActivityStackSupervisor.realStartActivityLocked(): ``` public class ActivityStackSupervisor{

boolean realStartActivityLocked( ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig ) { ... ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken);

clientTransaction.addCallback(LaunchActivityItem.obtain(...));

// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
    boolean forward = dc.isNextTransitionForward()
    lifecycleItem = ResumeActivityItem.obtain(forward);
} else {
    lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);

// Schedule transaction.
mService.getLifecycleManager()
  .scheduleTransaction(clientTransaction);
...

} } ```

到目前為止,我們看到的所有方法呼叫都發生在 system_server 程序中。 ClientLifecycleManager.scheduleTransaction() 在應用程序中對 ActivityThread.scheduleTransaction() 進行 IPC 呼叫,呼叫 ClientTransactionHandler.scheduleTransaction() 將 EXECUTE_TRANSACTION 訊息放入主執行緒訊息佇列中: ``` public abstract class ClientTransactionHandler {

/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(
      ActivityThread.H.EXECUTE_TRANSACTION,
      transaction
    );
}

} ```

當 EXECUTE_TRANSACTION 被處理時,它呼叫 TransactionExecutor.execute()。

實際 Activity 啟動

TransactionExecutor.execute() 呼叫 TransactionExecutor.performLifecycleSequence() 呼叫回 ActivityThread 來建立、啟動和恢復活動: ``` public class TransactionExecutor {

private void performLifecycleSequence(...) { for (int i = 0, state; i < path.size(); i++) { state = path.get(i); switch (state) { case ON_CREATE: mTransactionHandler.handleLaunchActivity(...); break; case ON_START: mTransactionHandler.handleStartActivity(...); break; case ON_RESUME: mTransactionHandler.handleResumeActivity(...); break; case ON_PAUSE: mTransactionHandler.handlePauseActivity(...); break; case ON_STOP: mTransactionHandler.handleStopActivity(...); break; case ON_DESTROY: mTransactionHandler.handleDestroyActivity(...); break; case ON_RESTART: mTransactionHandler.performRestartActivity(...); break; } } } } ```

第一個繪製

讓我們看看從 ActivityThread.handleResumeActivity() 導致第一次繪製的呼叫序列:

Choreographer.scheduleFrameLocked() 將 MSG_DO_FRAME 訊息放入主執行緒訊息佇列中。

處理 MSG_DO_FRAME 時,它呼叫 Choreographer.doFrame(),後者呼叫 ViewRootImpl.doTraversal(),後者執行測量傳遞、佈局傳遞,最後是檢視層次結構上的第一個繪製傳遞(請參閱 Android 如何繪製檢視)。