渲染Android应用程序的第一帧

图片



大家好!这篇文章是的延续约一个深入了解下载和启动一个Android应用程序的过程。今天,我们将更进一步,讨论启动应用程序的主要活动以及系统应呈现第一帧的时刻。请在猫下。



根据官方文档,正在运行的应用程序过程负责执行以下步骤:



  1. 创建Application类的对象。
  2. 启动主线程(MainThread或UiThread)。
  3. 创建清单清单中指定的开始活动。
  4. 扩展视图(膨胀,膨胀)。即,创建写入xml文件的视图。
  5. 屏幕上视图的大小(View.measure())和位置(View.layout())的布局。
  6. 执行初始渲染。


绘制第一帧后,系统进程替换显示的背景窗口,将其替换为Application Activity用户现在可以与应用程序进行交互。



图片



现在,让我们仔细看看所有步骤。



主流开始



在上一篇文章中,我们了解到:



  • , ActivityThread.main(), IPC- ActivityManagerService.attachApplication() system_server.
  • system_server IPC- ActivityThread.bindApplication(), BIND_APPLICATION MessageQueue .
  • 当IPC调用ActivityManagerService时。attachApplication()完成,ActivityThread。main()调用Looper。loop(),它将永远循环(只要应用程序正在运行),并将处理进入MessageQueue的消息
  • 要处理的第一条消息是BIND_APPLICATION此时,将调用ActivityThread方法。handleBindApplication(),它将加载APK和其他应用程序组件。


图片



重要一点:在对ActivityManagerService方法进行IPC调用之前,应用程序进程的主线程中什么都不会发生。attachApplication()



规划活动的启动



让我们看看调用ActivityThread方法后在system_server进程中会发生什么。bindApplication()



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;
  }
}


与启动活动相关的字符串是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 */
          )
        }
      }
    }
    ...
  }
}


该代码执行以下操作:



  • 绕过每个显示。
  • 获取此显示的重点活动堆栈。
  • 循环遍历目标活动堆栈的每个活动。
  • 如果Activity属于正在运行的进程,则将调用ActivityStackSupervisor方法。realStartActivityLocked()请注意,如果Activity在堆栈顶部,则andResume参数将为true。


这就是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进行IPC调用。scheduleTransaction()在应用程序中调用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方法。执行()



现在您可以更新该图:



图片



实际启动活动



方法TransactionExecutor。execute()调用TransactionExecutor。

performLifecycleSequence()继而对ActivityThread进行回调,以创建(创建),启动(开始)和继续(恢复)Activity:



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()
  • WindowManagerImpl。addView()
  • WindowManagerGlobal。addView()
  • ViewRootImpl。setView()
  • ViewRootImpl。requestLayout()
  • ViewRootImpl。scheduleTraversals()
  • 编舞。postCallback()
  • 编舞。scheduleFrameLocked()


编舞方法。scheduleFrameLocked()MSG_DO_FRAME消息排队



图片



处理MSG_DO_FRAME消息时,将调用Choreographer方法。doFrame(),它依次调用ViewRootImpl。doTraversal(),它传递了度量传递布局传递,最后是第一个绘制传递通过了视图层次结构:



图片



结论



我们首先对系统创建应用程序流程时发生的事情有一个高层次的了解:



图片



现在我们知道“幕后”到底发生了什么:



图片



现在,让我们连接上一篇文章中的图表,从用户点击应用程序图标到绘制第一个图标。框架:



图片



现在我们有了完整的图片,我们可以开始思考如何正确控制冷启动。下一篇文章将有关!再见。



All Articles