Android第一個繪製的Surface
如何監控冷啟動
一旦系統建立了應用程式程序,應用程式程序就負責接下來的階段:
-
建立應用程式物件。
-
啟動主執行緒。
-
建立主要 Activity 。
-
填充 View 。
-
佈置螢幕。
-
進行初始化繪製。
一旦應用程序完成了第一次繪製,系統程序就會換出當前顯示的背景視窗,用主活動替換它。 此時,使用者可以開始使用該應用程式。
主執行緒開始
在上一篇博文中,我們瞭解到:
當應用程式程序啟動時,它會呼叫 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() 導致第一次繪製的呼叫序列:
- ActivityThread.handleResumeActivity()
- ➡️ WindowManagerImpl.addView()
- ➡️ WindowManagerGlobal.addView()
- ➡️ ViewRootImpl.setView()
- ➡️ ViewRootImpl.requestLayout()
- ➡️ ViewRootImpl.scheduleTraversals()
- ➡️ Choreographer.postCallback()
- ➡️ Choreographer.scheduleFrameLocked()
Choreographer.scheduleFrameLocked() 將 MSG_DO_FRAME 訊息放入主執行緒訊息佇列中。
處理 MSG_DO_FRAME 時,它呼叫 Choreographer.doFrame(),後者呼叫 ViewRootImpl.doTraversal(),後者執行測量傳遞、佈局傳遞,最後是檢視層次結構上的第一個繪製傳遞(請參閱 Android 如何繪製檢視)。