Merender bingkai pertama aplikasi Android

gambar



Halo semuanya! Postingan ini merupakan kelanjutan dari postingan tentang proses mendalami pengunduhan dan peluncuran aplikasi Android. Hari ini kita akan melangkah lebih jauh dan membahas momen ketika Aktivitas utama aplikasi diluncurkan dan sistem harus merender bingkai pertama. Tolong, di bawah kucing.



Mengikuti dokumentasi resmi, proses aplikasi yang sedang berjalan bertanggung jawab untuk melakukan langkah-langkah berikut:



  1. Membuat objek kelas Aplikasi.
  2. Mulai utas utama (MainThread alias UiThread).
  3. Pembuatan Aktivitas awal, yang ditentukan dalam manifes.
  4. Ekspansi (inflasi, penggelembungan) pandangan. Yaitu, pembuatan tampilan, yang didaftarkan di file xml.
  5. Tata letak ukuran (View.measure ()) dan penempatan (View.layout ()) tampilan di layar.
  6. Melakukan rendering awal.


Setelah bingkai pertama digambar, proses sistem menggantikan jendela latar belakang yang ditampilkan, menggantinya dengan Aktivitas Aplikasi. Pengguna sekarang dapat berinteraksi dengan aplikasi.



gambar



Sekarang mari kita lihat lebih dekat semua langkahnya.



Mulai dari arus utama



Di posting sebelumnya, kita belajar:



  • Saat proses aplikasi dimulai, itu memanggil metode ActivityThread. main () , yang membuat permintaan IPC pemblokiran ke metode ActivityManagerService. attachApplication () dalam proses system_server .
  • system_server IPC- ActivityThread.bindApplication(), BIND_APPLICATION MessageQueue .
  • IPC- ActivityManagerService.attachApplication() , ActivityThread.main() Looper.loop(), ( ) MessageQueue.
  • , BIND_APPLICATION. ActivityThread.handleBindApplication(), APK .


gambar



Poin penting: tidak ada yang terjadi di thread utama proses aplikasi hingga panggilan IPC ke ActivityManagerService dibuat. attachmentApplication () .



Merencanakan peluncuran Aktivitas



Mari kita lihat apa yang terjadi dalam proses system_server setelah memanggil metode ActivityThread. 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;
  }
}


String yang relevan dengan peluncuran Aktivitas adalah mAtmInternal. attachmentApplication (...) . Metode tersebut memanggil ActivityTaskManagerService. attachApplication () , yang selanjutnya memanggil RootActivityContainer. attachmentApplication () :



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 */
          )
        }
      }
    }
    ...
  }
}


Kode tersebut melakukan hal berikut:



  • Lewati setiap tampilan.
  • Mendapatkan tumpukan Aktivitas terfokus untuk tampilan ini.
  • Perulangan melalui setiap Aktivitas tumpukan Aktivitas target.
  • Jika Aktivitas termasuk dalam proses yang sedang berjalan, maka metode ActivityStackSupervisor akan dipanggil. realStartActivityLocked () . Perhatikan bahwa parameter andResume akan bernilai true jika Aktivitas berada di puncak tumpukan.


Seperti inilah tampilan metode 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);
    ...
  }
}


Semua panggilan metode yang telah kita lihat terjadi dalam proses system_server . ClientLifecycleManager. scheduleTransaction () melakukan panggilan IPC ke ActivityThread. scheduleTransaction () dalam proses aplikasi yang memanggil ClientTransactionHandler. scheduleTransaction () untuk mengantrekan pesan 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
        );
    }
}


Saat memproses pesan EXECUTE_TRANSACTION , metode TransactionExecutor dipanggil. jalankan () .



Sekarang Anda dapat memperbarui diagram:



gambar



Peluncuran sebenarnya dari Aktivitas



Metode TransactionExecutor. eksekusi () memanggil TransactionExecutor.

performLifecycleSequence () , yang pada gilirannya membuat panggilan balik di ActivityThread untuk membuat ( membuat ), memulai ( memulai ) dan melanjutkan ( melanjutkan ) Aktivitas:



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


Memperbarui diagram:



gambar



Bingkai pertama



Mari kita lihat urutan pemanggilan metode yang mengarah ke rendering frame pertama:



  • ActivityThread. handleResumeActivity ()
  • WindowManagerImpl. addView ()
  • WindowManagerGlobal. addView ()
  • ViewRootImpl. setView ()
  • ViewRootImpl. requestLayout ()
  • ViewRootImpl. scheduleTraversals ()
  • Koreografer. postCallback ()
  • Koreografer. scheduleFrameLocked ()


Metode koreografer. scheduleFrameLocked () mengantri pesan MSG_DO_FRAME :



gambar



Saat memproses pesan MSG_DO_FRAME , metode koreografer dipanggil. doFrame () , yang pada gilirannya memanggil ViewRootImpl. doTraversal () , yang meneruskan langkah ukur dan tata letak , dan terakhir gambar pertama melewati hierarki tampilan:



gambar



Kesimpulan



Kita mulai dengan pemahaman tingkat tinggi tentang apa yang terjadi ketika sistem membuat proses aplikasi:



gambar



Sekarang kita tahu apa yang sebenarnya terjadi "di bawah tenda":



gambar



Sekarang mari kita hubungkan diagram dari posting sebelumnya, dari saat pengguna mengetuk ikon aplikasi hingga yang pertama digambar. bingkai:



gambar



Sekarang setelah kita memiliki gambaran lengkap, kita dapat mulai mencari cara untuk mengontrol start cold dengan benar. Posting selanjutnya adalah tentang itu! Sampai jumpa.



All Articles