Đo thời gian tải và hiển thị màn hình bằng Giám sát hiệu suất Firebase

1. Giới thiệu

Cập nhật lần cuối: 2021-03-11

Tại sao chúng ta cần đo lường hiệu suất của Lượt xem?

Lượt xem là một phần quan trọng của ứng dụng Android ảnh hưởng trực tiếp đến trải nghiệm người dùng. Ví dụ: Hoạt động hoặc Đoạn của bạn chứa giao diện người dùng chứa các thành phần Chế độ xem mà người dùng tương tác. Người dùng không thể xem toàn bộ nội dung của giao diện người dùng cho đến khi nó được vẽ hoàn toàn trên màn hình. Màn hình chậm và bị treo sẽ trực tiếp làm giảm sự tương tác của người dùng với ứng dụng của bạn và tạo ra trải nghiệm người dùng không tốt.

Giám sát hiệu suất Firebase không cung cấp sẵn các số liệu hiệu suất này phải không?

Giám sát hiệu suất Firebase tự động thu thập một số dữ liệu hiệu suất ngay lập tức, chẳng hạn như thời gian bắt đầu ứng dụng của bạn (tức là thời gian tải chỉ cho Hoạt động đầu tiên của bạn) và hiệu suất hiển thị màn hình (tức là khung hình chậm và bị treo cho Hoạt động chứ không phải cho mảnh vỡ). Tuy nhiên, các ứng dụng trong ngành thường không có nhiều Hoạt động mà chỉ có một Hoạt động và nhiều Phân đoạn. Ngoài ra, nhiều ứng dụng thường triển khai Chế độ xem tùy chỉnh của riêng chúng cho các trường hợp sử dụng phức tạp hơn. Vì vậy, việc hiểu cách đo thời gian tải và hiệu suất hiển thị màn hình của cả Hoạt động và Mảnh bằng cách đo lường dấu vết mã tùy chỉnh trong ứng dụng của bạn thường rất hữu ích. Bạn có thể dễ dàng mở rộng lớp học lập trình này để đo lường hiệu suất của các thành phần Chế độ xem tùy chỉnh.

Bạn sẽ học được gì

  • Cách thêm Giám sát hiệu suất Firebase vào ứng dụng Android
  • Hiểu cách tải Hoạt động hoặc Đoạn
  • Cách thiết lập dấu vết mã tùy chỉnh để đo thời gian tải của Hoạt động hoặc Đoạn
  • Hiểu về Kết xuất màn hình và khung hình Chậm/Đông cứng là gì
  • Cách thiết lập các dấu vết mã tùy chỉnh bằng số liệu để ghi lại màn hình Chậm/Đông cứng
  • Cách xem số liệu được thu thập trong bảng điều khiển Firebase

Những gì bạn cần

  • Android Studio 4.0 trở lên
  • Thiết bị/trình mô phỏng Android
  • Phiên bản Java 8 trở lên

2. Bắt đầu thiết lập

Lấy mã

Chạy các lệnh sau để sao chép mã mẫu cho lớp học lập trình này. Thao tác này sẽ tạo một thư mục có tên codelab-measure-android-view-performance trên máy của bạn:

$ git clone https://github.com/FirebaseExtended/codelab-measure-android-view-performance.git
$ cd codelab-measure-android-view-performance

Nếu bạn không có git trên máy, bạn cũng có thể tải mã trực tiếp từ GitHub.

Nhập dự án measure-view-performance-start vào Android Studio. Bạn có thể sẽ thấy một số lỗi biên dịch hoặc có thể là cảnh báo về tệp google-services.json bị thiếu. Chúng tôi sẽ sửa lỗi này trong phần tiếp theo của bước này.

Trong lớp học lập trình này, chúng ta sẽ sử dụng plugin Hỗ trợ Firebase để đăng ký ứng dụng Android với dự án Firebase và thêm các tệp cấu hình, plugin và phần phụ thuộc Firebase cần thiết vào dự án Android của chúng ta — tất cả đều từ trong Android Studio !

Kết nối ứng dụng của bạn với Firebase

  1. Đi tới Android Studio / Trợ giúp > Kiểm tra các bản cập nhật để đảm bảo rằng bạn đang sử dụng phiên bản mới nhất của Android Studio và Trợ lý Firebase.
  2. Chọn Công cụ > Firebase để mở ngăn Trợ lý .

e791bed0999db1e0.png

  1. Chọn Giám sát hiệu suất để thêm vào ứng dụng của bạn, sau đó nhấp vào Bắt đầu với Giám sát hiệu suất .
  2. Nhấp vào Kết nối với Firebase để kết nối dự án Android của bạn với Firebase (thao tác này sẽ mở bảng điều khiển Firebase trong trình duyệt của bạn) .
  3. Trong bảng điều khiển Firebase, hãy nhấp vào Thêm dự án , sau đó nhập tên dự án Firebase (nếu bạn đã có dự án Firebase, bạn có thể chọn dự án hiện có đó thay thế) . Nhấp vào Tiếp tục và chấp nhận các điều khoản để tạo dự án Firebase và Ứng dụng Firebase mới.
  4. Tiếp theo, bạn sẽ thấy hộp thoại Kết nối ứng dụng Firebase mới với dự án Android Studio của mình.

42c498d28ead2b77.png

  1. Quay lại Android Studio, trong ngăn Trợ lý , bạn sẽ thấy xác nhận rằng ứng dụng của bạn đã được kết nối với Firebase.

dda8bdd9488167a0.png

Thêm Giám sát hiệu suất vào ứng dụng của bạn

Trong ngăn Trợ lý trong Android Studio, hãy nhấp vào Thêm giám sát hiệu suất vào ứng dụng của bạn .

Bạn sẽ thấy hộp thoại Chấp nhận thay đổi , sau đó Android Studio sẽ đồng bộ hóa ứng dụng của bạn để đảm bảo rằng tất cả các phần phụ thuộc cần thiết đã được thêm vào.

9b58145acc4be030.png

Cuối cùng, bạn sẽ thấy thông báo thành công trong ngăn Trợ lý trong Android Studio cho biết tất cả các phần phụ thuộc đã được thiết lập chính xác.

aa0d46fc944e0c0b.png

Là một bước bổ sung, hãy bật ghi nhật ký gỡ lỗi bằng cách làm theo hướng dẫn trong bước "(Tùy chọn) Bật ghi nhật ký gỡ lỗi". Các hướng dẫn tương tự cũng có sẵn trong tài liệu công cộng .

3. Chạy ứng dụng

Nếu bạn đã tích hợp thành công ứng dụng của mình với SDK giám sát hiệu suất thì dự án sẽ được biên dịch ngay bây giờ. Trong Android Studio, nhấp vào Chạy > Chạy 'ứng dụng' để xây dựng và chạy ứng dụng trên thiết bị/trình mô phỏng Android được kết nối của bạn.

Ứng dụng này có hai nút đưa bạn đến Hoạt động và Đoạn tương ứng, như sau:

410d8686b4f45c33.png

Trong các bước sau của lớp học lập trình này, bạn sẽ tìm hiểu cách đo thời gian tải và hiệu suất hiển thị màn hình của Hoạt động hoặc Đoạn.

4. Hiểu cách tải một Hoạt động hoặc Đoạn

Trong bước này, chúng ta sẽ tìm hiểu xem hệ thống đang làm gì trong quá trình tải Hoạt động hoặc Đoạn.

Hiểu cách tải một Hoạt động

Đối với một Hoạt động, thời gian tải được xác định là thời gian bắt đầu từ khi đối tượng Hoạt động được tạo cho đến khi Khung hình đầu tiên được vẽ hoàn toàn trên màn hình ( đây là lúc người dùng của bạn sẽ nhìn thấy giao diện người dùng hoàn chỉnh cho Hoạt động lần đầu tiên thời gian ). Để đo xem ứng dụng của bạn có được vẽ hoàn toàn hay không, bạn có thể sử dụng phương thức reportFullyDrawn() để đo thời gian trôi qua giữa lúc khởi chạy ứng dụng và hiển thị đầy đủ tất cả tài nguyên cũng như xem phân cấp.

Ở cấp độ cao, khi ứng dụng của bạn gọi startActivity(Intent) , hệ thống sẽ tự động thực hiện các quy trình sau. Mỗi quy trình cần có thời gian để hoàn thành, điều này làm tăng thêm khoảng thời gian từ khi tạo Hoạt động đến khi người dùng nhìn thấy giao diện người dùng cho Hoạt động trên màn hình của họ.

c20d14b151549937.png

Hiểu cách tải một mảnh

Tương tự như Hoạt động, thời gian tải cho Phân đoạn được xác định là thời gian bắt đầu từ khi Phân đoạn được gắn vào Hoạt động chủ của nó cho đến khi Khung hình đầu tiên cho Chế độ xem phân đoạn được vẽ hoàn toàn trên màn hình.

5. Đo thời gian tải của một Hoạt động

Độ trễ ở khung đầu tiên có thể dẫn đến trải nghiệm không tốt cho người dùng, vì vậy điều quan trọng là phải hiểu mức độ trễ tải ban đầu mà người dùng của bạn đang gặp phải. Bạn có thể sử dụng công cụ theo dõi mã tùy chỉnh để đo thời gian tải này:

  1. Bắt đầu theo dõi mã tùy chỉnh (có tên TestActivity-LoadTime ) trong lớp Hoạt động ngay khi đối tượng Hoạt động được tạo.

TestActivity.java

public class TestActivity extends AppCompatActivity {   
    // TODO (1): Start trace recording as soon as the Activity object is created.
    private final Trace viewLoadTrace = FirebasePerformance.startTrace("TestActivity-LoadTime");

    // ...

}
  1. Ghi đè lệnh gọi lại onCreate() và thêm Chế độ xem bằng phương thức setContentView() .
@Override     
public void onCreate(Bundle savedInstanceState) {    
    super.onCreate(savedInstanceState);          

    // Current Activity's main View (as defined in the layout xml file) is inflated after this            
    setContentView(R.layout.activity_test);          

    // ...

    // TODO (2): Get the View added by Activity's setContentView() method.         
    View mainView = findViewById(android.R.id.content);     

    // ...
}
  1. Chúng tôi đã bao gồm việc triển khai FistDrawListener , có hai lệnh gọi lại: onDrawingStart()onDrawingFinish() (xem phần tiếp theo bên dưới để biết thêm chi tiết về FirstDrawListener và những gì có thể ảnh hưởng đến hiệu suất của nó) . Đăng ký FirstDrawListener ở cuối lệnh gọi lại onCreate() của Hoạt động. Bạn nên dừng viewLoadTrace trong lệnh gọi lại onDrawingFinish() .

TestActivity.java

    // TODO (3): Register the callback to listen for first frame rendering (see
    //  "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when View drawing is
    //  finished.
    FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {              
        @Override             
        public void onDrawingStart() {       
          // In practice you can also record this event separately
        }

        @Override             
        public void onDrawingFinish() {
            // This is when the Activity UI is completely drawn on the screen
            viewLoadTrace.stop();             
        }         
    });
  1. Chạy lại ứng dụng. Sau đó, lọc logcat bằng " Chỉ số theo dõi ghi nhật ký ". Nhấn vào nút LOAD ACTIVITY và tìm nhật ký như bên dưới:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 Xin chúc mừng! Bạn đã đo thành công thời gian tải của một Hoạt động và báo cáo dữ liệu đó cho Giám sát hiệu suất Firebase. Chúng ta sẽ xem chỉ số được ghi lại trong bảng điều khiển Firebase sau trong lớp học lập trình này.

Mục đích của FirstDrawListener

Trong phần ngay trên, chúng tôi đã đăng ký FirstDrawListener . Mục đích của FirstDrawListener là đo thời điểm khung đầu tiên bắt đầu và kết thúc vẽ.

Nó triển khai ViewTreeObserver.OnDrawListener và ghi đè lệnh gọi lại onDraw() được gọi khi cây View sắp được vẽ. Sau đó, nó sẽ gói kết quả để cung cấp hai lệnh gọi lại tiện ích onDrawingStart()onDrawingFinish() .

Bạn có thể tìm thấy mã hoàn chỉnh cho FirstDrawListener trong mã nguồn của lớp học lập trình này.

6. Đo thời gian tải của Fragment

Đo thời gian tải của Phân đoạn tương tự như cách chúng tôi đo lường thời gian tải cho Hoạt động nhưng có một số khác biệt nhỏ. Một lần nữa, chúng ta sẽ thiết lập một dấu vết mã tùy chỉnh :

  1. Ghi đè lệnh gọi lại onAttach() và bắt đầu ghi lại fragmentLoadTrace của bạn. Chúng tôi sẽ đặt tên cho dấu vết này Test-Fragment-LoadTime .

Như đã giải thích ở bước trước, đối tượng Fragment có thể được tạo bất cứ lúc nào nhưng nó chỉ hoạt động khi được gắn vào Hoạt động chủ của nó.

TestFragment.java

public class TestFragment extends Fragment {

   // TODO (1): Declare the Trace variable.
   private Trace fragmentLoadTrace;

   @Override
   public void onAttach(@NonNull Context context) {
       super.onAttach(context);

       // TODO (2): Start trace recording as soon as the Fragment is attached to its host Activity.
       fragmentLoadTrace = FirebasePerformance.startTrace("TestFragment-LoadTime");
   }
  1. Đăng ký FirstDrawListener trong lệnh gọi lại onViewCreated() . Sau đó, tương tự như ví dụ về Hoạt động, hãy dừng dấu vết trong onDrawingFinish() .

TestFragment.java

@Override
public void onViewCreated(@NonNull View mainView, Bundle savedInstanceState) {
   super.onViewCreated(mainView, savedInstanceState);

   // ...

   // TODO (3): Register the callback to listen for first frame rendering (see
   //  "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when view drawing is
   //  finished.
   FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {

       @Override
       public void onDrawingStart() {
           // In practice you can also record this event separately
       }

       @Override
       public void onDrawingFinish() {
           // This is when the Fragment UI is completely drawn on the screen
           fragmentLoadTrace.stop();
       }
   });
  1. Chạy lại ứng dụng. Sau đó, lọc logcat bằng " Chỉ số theo dõi ghi nhật ký ". Nhấn vào nút LOAD FRAGMENT và tìm nhật ký như bên dưới:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 Xin chúc mừng! Bạn đã đo thành công thời gian tải của một Mảnh và báo cáo dữ liệu đó cho Giám sát hiệu suất Firebase. Chúng ta sẽ xem chỉ số được ghi lại trong bảng điều khiển Firebase sau trong lớp học lập trình này.

7. Tìm hiểu về Kết xuất màn hình và khung hình Chậm/Đứng là gì

Kết xuất giao diện người dùng là hành động tạo khung từ ứng dụng của bạn và hiển thị khung đó trên màn hình. Để đảm bảo tương tác của người dùng với ứng dụng của bạn diễn ra suôn sẻ, ứng dụng của bạn phải hiển thị các khung hình trong thời gian dưới 16 mili giây để đạt được 60 khung hình/giây ( tại sao lại là 60 khung hình/giây? ). Nếu ứng dụng của bạn hiển thị giao diện người dùng chậm thì hệ thống buộc phải bỏ qua các khung và người dùng sẽ nhận thấy ứng dụng của bạn bị giật hình. Chúng tôi gọi đây là trò đùa .

Tương tự, khung hình bị cố định là khung giao diện người dùng mất nhiều thời gian hơn 700 mili giây để hiển thị. Sự chậm trễ này là một vấn đề vì ứng dụng của bạn dường như bị kẹt và không phản hồi với thao tác nhập của người dùng trong gần một giây trong khi khung đang hiển thị.

8. Đo khung hình Chậm/Đứng của một mảnh

Giám sát hiệu suất Firebase tự động ghi lại các khung hình chậm/đóng băng cho một Hoạt động ( nhưng chỉ khi đó là Tăng tốc phần cứng ). Tuy nhiên, tính năng này hiện không khả dụng cho Fragment. Các khung hình chậm/bị treo của một Mảnh được định nghĩa là các khung hình chậm/bị treo cho toàn bộ Hoạt động giữa các lệnh gọi lại onFragmentAttached()onFragmentDetached() trong vòng đời của Mảnh.

Lấy động lực từ lớp AppStateMonitor ( là một phần của SDK giám sát hiệu suất chịu trách nhiệm ghi lại dấu vết màn hình cho Hoạt động ), chúng tôi đã triển khai lớp ScreenTrace ( là một phần của kho mã nguồn lớp học lập trình này ). Lớp ScreenTrace có thể được kết nối với lệnh gọi lại vòng đời FragmentManager của Hoạt động để ghi lại các khung hình chậm/bị treo. Lớp này cung cấp hai API công khai:

  • recordScreenTrace() : Bắt đầu ghi lại dấu vết màn hình
  • sendScreenTrace() : Dừng ghi dấu vết màn hình và đính kèm số liệu tùy chỉnh để ghi lại số lượng khung hình Tổng, Chậm và Bị treo

Bằng cách đính kèm các chỉ số tùy chỉnh này, bạn có thể xử lý dấu vết màn hình cho Phân đoạn giống như dấu vết màn hình cho một Hoạt động và có thể hiển thị cùng với các dấu vết hiển thị màn hình khác trong Trang tổng quan hiệu suất của bảng điều khiển Firebase.

Dưới đây là cách ghi lại dấu vết màn hình cho Fragment của bạn:

  1. Khởi tạo lớp ScreenTrace trong Hoạt động lưu trữ Phân đoạn của bạn.

MainActivity.java

// Declare the Fragment tag
private static final String FRAGMENT_TAG = TestFragment.class.getSimpleName();

// TODO (1): Declare the ScreenTrace variable.
private ScreenTrace screenTrace;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // TODO (2): Initialize the ScreenTrace variable.
    screenTrace = new ScreenTrace(this, FRAGMENT_TAG);

    // ...
}
  1. Khi bạn tải Fragment của mình, hãy đăng ký FragmentLifecycleCallbacks và ghi đè các lệnh gọi lại onFragmentAttached()onFragmentDetached() . Chúng tôi đã làm điều này cho bạn. Bạn cần bắt đầu ghi lại dấu vết màn hình trong lệnh gọi lại onFragmentAttached() và dừng ghi trong lệnh gọi lại onFragmentDetached() .

MainActivity.java

private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
       new FragmentManager.FragmentLifecycleCallbacks() {

           @Override
           public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
               super.onFragmentAttached(fm, f, context);

               // TODO (3): Start recording the screen traces as soon as the Fragment is
               //  attached to its host Activity.
               if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
                   screenTrace.recordScreenTrace();
               }
           }

           @Override
           public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
               super.onFragmentDetached(fm, f);

               // TODO (4): Stop recording the screen traces as soon as the Fragment is
               //  detached from its host Activity.
               if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
                   screenTrace.sendScreenTrace();
               }

               // Unregister Fragment lifecycle callbacks after the Fragment is detached
               fm.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks);
           }
       };
  1. Chạy lại ứng dụng. Sau đó, nhấn vào nút LOAD FRAGMENT . Đợi vài giây rồi nhấp vào back button trên thanh điều hướng phía dưới.

Lọc logcat bằng " Logging tracemetric ", sau đó tìm các nhật ký như bên dưới:

I/FirebasePerformance: Logging trace metric: _st_MainActivity-TestFragment (duration: XXXms)

Lọc logcat bằng " FireperfViews ", sau đó tìm nhật ký như bên dưới:

D/FireperfViews: sendScreenTrace MainActivity-TestFragment, name: _st_MainActivity-TestFragment, total_frames: XX, slow_frames: XX, frozen_frames: XX

🎉 Xin chúc mừng! Bạn đã đo thành công khung hình Chậm/Đứng cho một Mảnh và báo cáo dữ liệu đó cho Giám sát hiệu suất Firebase. Chúng ta sẽ xem các chỉ số được ghi lại trong bảng điều khiển Firebase sau trong lớp học lập trình này.

9. Kiểm tra số liệu trong bảng điều khiển Firebase

  1. Trong logcat, hãy nhấp vào URL bảng điều khiển Firebase để truy cập trang chi tiết để theo dõi. ceb9d5ba51bb6e89.jpeg

Ngoài ra, trong bảng điều khiển Firebase , hãy chọn dự án có ứng dụng của bạn. Trong bảng điều khiển bên trái, tìm phần Release & Monitor , sau đó nhấp vào Performance .

  • Trong tab Trang tổng quan chính, cuộn xuống bảng dấu vết, sau đó nhấp vào tab Dấu vết tùy chỉnh . Trong bảng này, bạn sẽ thấy các dấu vết mã tùy chỉnh mà chúng tôi đã thêm trước đó cùng với một số dấu vết sẵn dùng , chẳng hạn như dấu vết _app_start .
  • Tìm hai dấu vết mã tùy chỉnh của bạn, TestActivity-LoadTimeTestFragment-LoadTime . Nhấp vào Thời lượng cho một trong hai để xem thêm chi tiết về dữ liệu được thu thập.

a0d8455c5269a590.png

  1. Trang chi tiết cho dấu vết mã tùy chỉnh hiển thị cho bạn thông tin về khoảng thời gian của dấu vết (tức là thời gian tải đo được).

5e92a307b7410d8b.png

  1. Bạn cũng có thể xem dữ liệu hiệu suất cho dấu vết màn hình tùy chỉnh của mình.
  • Quay lại tab Trang tổng quan chính, cuộn xuống bảng dấu vết, sau đó nhấp vào tab Hiển thị màn hình . Trong bảng này, bạn sẽ thấy các dấu vết màn hình tùy chỉnh mà chúng tôi đã thêm trước đó cùng với mọi dấu vết màn hình có sẵn , chẳng hạn như dấu vết MainActivity .
  • Tìm dấu vết màn hình tùy chỉnh của bạn, MainActivity-TestFragment . Nhấp vào tên theo dõi để xem dữ liệu tổng hợp về khung hình hiển thị chậm và bị treo.

ee7890c7e2c28740.png

10. Xin chúc mừng

Chúc mừng! Bạn đã đo thành công thời gian tải và hiệu suất hiển thị màn hình của Hoạt động và Đoạn bằng cách sử dụng Giám sát hiệu suất Firebase!

Những gì bạn đã hoàn thành

Cái gì tiếp theo

Firebase Performance cung cấp nhiều cách đo lường hiệu suất cho ứng dụng của bạn hơn là theo dõi tùy chỉnh. Nó tự động đo thời gian khởi động ứng dụng, dữ liệu hiệu suất của ứng dụng ở nền trước và ứng dụng ở chế độ nền . Đã đến lúc bạn kiểm tra các số liệu này trong Bảng điều khiển Firebase .

Ngoài ra, Firebase Performance còn cung cấp tính năng giám sát yêu cầu mạng HTTP/S tự động . Nhờ đó, bạn có thể dễ dàng thực hiện các yêu cầu mạng mà không cần viết một dòng mã nào. Bạn có thể thử gửi một số yêu cầu mạng từ ứng dụng của mình và tìm số liệu trong bảng điều khiển Firebase không?

Thưởng

Bây giờ bạn đã biết cách đo thời gian tải và hiệu suất kết xuất màn hình của Hoạt động/ Đoạn bằng cách sử dụng dấu vết mã tùy chỉnh, bạn có thể khám phá cơ sở mã nguồn mở của chúng tôi để xem liệu bạn có thể nắm bắt ngay các số liệu đó cho bất kỳ Hoạt động/ Đoạn nào không đó là một phần của ứng dụng? Vui lòng gửi PR nếu bạn muốn :-)

11. Học tập thưởng

Hiểu những gì đang xảy ra trong quá trình tải Hoạt động sẽ giúp bạn hiểu rõ hơn về đặc điểm hiệu suất của ứng dụng. Ở bước trước, chúng tôi đã mô tả ở mức độ cao những gì xảy ra trong quá trình tải Hoạt động nhưng sơ đồ sau đây mô tả từng giai đoạn chi tiết hơn nhiều.

cd61c1495fad7961.png