Android #3 - Vòng đời của Activity (Activity life-cycle) và tại sao chúng ta cần phải biết nó?

Tiếp nối bài viết Android #2 - Tìm hiểu về Intent, bài viết này chúng ta sẽ tìm hiểu một thành phần cực kì quan trọng trong Android, đó là Activity.

Activity sẽ là nơi để ứng dụng hiển thị những thành phần giao diện bên trong, mỗi một ứng dụng có thể có nhiều Activity và mỗi Activity lại có những vòng đời khác nhau, việc chúng ta nắm rõ được quy luật vòng đời của nó là điều tất yếu để quản lý các thành phần giao diện của ứng dụng.

Cũng giống như con người, Activity cũng sẽ có một quá trình vòng đời từ khi được tạo ra cho đến khi bị hủy, ở mỗi phần trong một vòng đời ấy, chúng ta sẽ quyết định làm những việc gì để có thể quản lý và tối ưu được chương trình ứng dụng.


Tiền đề trước khi bước vào

Theo Android Developers, các Activity thường sẽ có liên kết lỏng lẻo với nhau, và Activity nào đang được hiển thị trên màn hình thì được xem là Activity chính và được ưu tiên trong ứng dụng. Các Activity sẽ hoạt động theo một back stack (ngăn xếp), nghĩa là khi một Activity dừng lại, nó sẽ được đẩy vào ngăn xếp để lưu trữ và được lấy ra khi những Activity thêm vào sau đó đã được đẩy ra khỏi. Có thể hiểu nôm na các Activity sẽ hoạt động theo cơ chế "Last In, First Out" (LIFO).
Cơ chế hoạt động LIFO của các activity

Mỗi khi một Activity bị dừng hoặc được khởi tạo, ứng dụng sẽ nắm bắt các sự kiện này thông qua các phương thức được gọi là vòng đời của Activity, khi đó nó sẽ cho bạn cơ hội để thực hiện những tác vụ cụ thể sao cho phù hợp với mục đích của bạn. Chẳng hạn khi bạn khởi chạy một ứng dụng lưu trữ kho hàng thì tại phương thức khởi tạo, chúng ta phải truy database trước khi xuất dữ liệu trên giao diện, khi đóng ứng dụng đi, chúng ta đóng kết nối với database trước khi kết thúc vòng đời của Activity đó.

Bên trên là ví dụ cơ bản về tầm quan trọng của vòng đời trong Activity. Nhưng trên thực tế sẽ phát sinh khá nhiều vấn đề trong quá trình chúng ta quản lý ứng dụng. Tùy từng trường hợp cụ thể thì chúng ta sẽ thực hiện những công việc cần thiết để bảo đảm cho ứng dụng hoạt động đúng.

Bên cạnh Activity, còn có một thứ khác được gọi là Fragment (hay còn được cộng đồng AndroidDev gọi là sub-activity). Fragment cũng có vòng đời như Activity, nhưng vấn đề này mình sẽ đề cập ở một bài viết khác.

Vòng đời của Activity

Vòng đời của Activity có sơ đồ hoạt động như sau:
Vòng đời của Activity
Như các bạn thấy, onCreate() onDestroy() là 2 phương thức chỉ được gọi một lần duy nhất trong suốt vòng đời. Do đó mọi thiết lập ánh xạ viewtác vụ khởi động khác sẽ được thực hiện trong onCreate() và sẽ không bao giờ gọi lại cho đến khi onDestroy() được gọi. Do đó khi cần thiết lập lại giao diện, ứng dụng sẽ tự động hủy nó đi và bắt đầu một vòng đời mới. Khi đó mọi thiết lập, dữ liệu mà bạn thực hiện trong các bước onStart(), onResume() đều sẽ bị mất đi nếu bạn không lưu lại tại một vùng nhớ nào đó trong điện thoại.

Để hiểu rõ hơn, chúng ta sẽ cùng đi sơ lược qua các trường hợp:

Trường hợp 1: Khởi chạy một Activity mới

Như ở bài trước về Intent, chúng ta đã nắm được cách khởi chạy một Activity mới, bạn có thể tìm hiểu thêm tại đây!
Trước tiên, mình sẽ tạo thêm một Activity và đặt tên là SecondActivity.
Sau đó mình truy xuất các phương thức vòng đời bên trong cả 2 Activity và log lại bên trong mỗi phương thức. Bên trong MainActivity, mình sẽ thêm một button để khởi chạy SecondActivity:
/* MainActivity.java */
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toast.makeText(this, "MainActivity: onCreate()", Toast.LENGTH_LONG).show();
        // Ánh xạ ButtonView
        Button btn = findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, SecondActivity.class));
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this, "MainActivity: onStart()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "MainActivity: onResume()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Toast.makeText(this, "MainActivity: onRestart()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this, "MainActivity: onPause()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast.makeText(this, "MainActivity: onStop()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "MainActivity: onDestroy()", Toast.LENGTH_LONG).show();
    }
}
/* SecondActivity.java */
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Toast.makeText(this, "SecondActivity: onCreate()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this, "SecondActivity: onStart()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "SecondActivity: onResume()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Toast.makeText(this, "SecondActivity: onRestart()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this, "SecondActivity: onPause()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast.makeText(this, "SecondActivity: onStop()", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "SecondActivity: onDestroy()", Toast.LENGTH_LONG).show();
    }
}
Khởi chạy ứng dụng, MainActivity sẽ được khởi tạo. Khi đó, onCreate() sẽ được gọi đầu tiên và đứng lại tại onResume(), chứng tỏ MainActivity đang được chạy trên màn hình.

Sau đó chúng ta nhấn vào button để khởi chạy SecondActivity, khi đó onPause() của MainActivity sẽ được gọi và onStop() được truy xuất sau khi SecondActivity đã được khởi chạy thành công.

Tiếp tục nhấn nút Back, khi đó các Activity sẽ tuân theo cơ chế LIFO, do đó SecondActivity sẽ bị hủy (onDestroy()) và MainActivity được khởi chạy trở lại.

Trường hợp 2: Khởi chạy Dialog


Tính chất của Dialog là khi được khởi chạy, nó sẽ đè lên Activity khác nhưng vẫn còn nhìn thấy Activity đó.
Để kiểm tra trường hợp này, bạn có thể cài đặt SecondActivity thành dialog trong file manifest như sau:
<activity android:name=".SecondActivity" 
                 android:theme="@style/Theme.AppCompat.Dialog"></activity>
Tương tự như trường hợp 1, MainActivity được khởi tạo.

Nhấn vào nút button, SecondActivity sẽ khởi chạy dưới dạng một Dialog, khi đó phương thức onPause() sẽ được gọi trong MainActivity nhưng tuyệt nhiên không thấy onStop() được gọi.

Lý do là vì chúng ta vẫn còn nhìn thấy MainActivity ở phía sau mà không phải bị che khuất đi như trong trường hợp 1.

Trường hợp 3: Xoay điện thoại


Khi xoay điện thoại, phương thức onDestroy() sẽ được gọi ra để hủy hoàn toàn giao diện của Activity. Sau đó phương thức onCreate() được gọi lại để thiết lập lại giao diện cho phù hợp với giao diện nằm ngang.

Kết luận

Trước khi kết thúc bài viết, một vấn đề được đặt ra là làm thế nào để có thể giữ được trạng thái của Activity sau khi chúng ta xoay màn hình?
Giả sử trong Activity của bạn có một EditText và bạn nhập một vài từ vào đó, sau đó xoay màn hình thì tất cả những từ bạn vừa nhập đều sẽ bị mất vì onDestroy() sẽ được gọi và onCeate() sẽ được khởi tạo trở lại.

Điều này mình sẽ để dành cho các bạn!
Thanh Dương

Android #3 - Vòng đời của Activity (Activity life-cycle) và tại sao chúng ta cần phải biết nó? Android #3 - Vòng đời của Activity (Activity life-cycle) và tại sao chúng ta cần phải biết nó? Reviewed by Duong-Tran Thanh on 9/18/2019 03:08:00 CH Rating: 5

Không có bình luận nào!

Được tạo bởi Blogger.
BACK TO TOP