Android – Thao tác với Activity

5/5 - (1 vote)

Trong bài này chúng ta sẽ tìm hiểu về vòng đời của một Activity, thường thì những kiến thức dưới đây cũng không được áp dụng nhiều nhưng chúng ta cũng nên tìm hiểu sơ qua.

Không giống như các ngôn ngữ như C++, Java… các ứng dụng bắt đầu chạy từ một hàm có tên là main(), khi người dùng chạy ứng dụng Android thì ứng dụng sẽ tạo một đối tượng Activity để tương tác với người dùng, và đối tượng Activity này còn có các trạng thái khác nhau trong quá trình chạy nữa. Ví dụ như khi mới bắt đầu khởi động ứng dụng thì Activity sẽ thay thế hệ điều hành làm công việc nhận và xử lý các thông tin được gửi tới từ người dùng, tại đây hệ điều hành sẽ gọi các phương thức cần thiết để khởi tạo các thành phần chủ chốt. Khi người dùng thực hiện một hành động mà có tạo ra một Activity mới hay chuyển sang dùng một ứng dụng khác, hệ điều hành lại gọi các phương thức cần thiết khác để khởi tạo còn Activity hiện tại sẽ được chuyển sang trạng thái background, tức là Activity này không còn hiện lên trên màn hình nữa nhưng nó không bị xóa đi mà vẫn còn nằm đâu đó bên dưới hệ điều hành.

Cũng vì Activity có những trạng thái khác biệt như thế nên chúng ta cũng nên tùy biến ứng dụng theo Activity nữa, ví dụ như khi chúng ta xây dựng một ứng dụng xem video, khi người dùng thoát khỏi activity thì chúng ta nên cho tạm dừng các công việc decode, hiển thị frame, ngắt kết nối mạng…v.v rồi khi nào người dùng quay trở lại thì chúng ta mở lại video tại vị trí đã dừng.

Các phương thức Activity

Trong quá trình chạy của một Activity, hệ điều hành sẽ gọi một số phương thức theo một thứ tự nhất định, và mỗi phương thức này sẽ chuyển ứng dụng sang các trạng thái khác nhau. Chúng ta có thể xem các phương thức và trạng thái tương ứng trong hình dưới, trong đó ứng dụng bắt đầu từ phương thức onCreate() và quá trình chạy di chuyển dần lên phía trên phương thức onResume(), quá trình hủy đi dần dần xuống dưới phương thức onDestroy().

basic-lifecycle-paused

Ngoài ra Activity còn có thể đi từ trạng thái Paused (tạm dừng) và Stopped (dừng) quay lại Resumed (phục hồi).

Thường thì các phương thức này được xử lý tự động bởi hệ điều hành, nhưng cũng có một vài trường hợp chúng ta phải override lại giống như với phương thức onCreate(). Việc override các phương thức đảm bảo ứng dụng của chúng ta chạy tốt trong mọi tình huống như không bị crash khi có cuộc gọi đến hoặc người dùng chuyển sang một ứng dụng khác, hay không làm tiêu tốn tài nguyên nhiều khi người dùng không tương tác với ứng dụng, không bị ảnh hưởng bởi thao tác xoay thiết bị…

Trong hình trên chúng ta đã thấy một Activity có nhiều trạng thái khác nhau, nhưng thực ra chỉ có 3 trạng thái là có thể tồn tại trong khoảng thời gian dài là Resumed, PausedStopped. Trạng thái Resumed là trạng thái mà Activity đó đang thực sự hoạt động và tương tác với người dùng. Trạng thái Paused xảy ra khi có một Activity khác được sinh ra và thực hiện việc thao tác với người dùng thay cho Activity cũ, lúc này Activity cũ sẽ không nhận tương tác với người dùng và xử lý chúng nữa. Trạng thái Stopped là trạng thái khi Activity không còn hiện hình nữa, lúc này Activity không bị xóa nhưng cũng không nhận tương tác với người dùng.

Các trạng thái còn lại là Created, StartedDestroyed chỉ xảy ra trong một khoảng thời gian nhất định và hầu như không còn xảy ra sau đó nữa.

Khai báo main Activity

Một ứng dụng có thể có nhiều Activity, nhưng phải có một Activity chính được khởi tạo khi người dùng chạy chương trình, hệ điều hành sẽ gọi phương thức onCreate() của Activity này.

Chúng ta khai báo Activity chính trong file AndroidManifest.xml nằm ở thư mục gốc của project. Ở đây chúng ta khai báo thẻ intent-filter với thẻ actioncategory như sau:

<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Nếu chúng ta không khai báo main Activity nào thì ứng dụng sẽ không hiện ra trên màn hình của thiết bị.

Tạo Activity

Hầu hết các ứng dụng đều có nhiều hơn một Activity cho phép người dùng thực hiện nhiều công việc khác nhau. Khi thiết kế một Activity thì chúng ta phải override phương thức onCreate(), phương thức này sẽ làm các công việc mang tính khởi tạo như khởi tạo giao diện người dùng, khai báo biến, hằng số…v.v Ví dụ:

TextView textView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);
    textView = (TextView) findViewById(R.id.textView);
}

Sau khi hệ điều hành hoàn tất các công việc trong phương thức onCreate() thì sẽ gọi đến 2 phương thức onStart()onResume(). Tham số của phương thức onCreate() là một đối tượng Bundle, chúng ta sẽ tìm hiểu về đối tượng này sau.

Hủy Activity

Có phương thức khởi tạo Activity thì cũng sẽ có phương thức hủy Activity và đó là phương thức onDestroy(), phương thức này được gọi bởi hệ điều hành khi ứng dụng thông báo cho hệ điều hành biết là nó đã hoàn thành công việc và chuẩn bị xóa khỏi bộ nhớ.

Hầu như chúng ta không phải override lại phương thức này vì các công việc như dọn dẹp bộ nhớ, xóa biến…v.v đều được làm tự động bởi hệ điều hành. Tuy nhiên chúng ta nên override lại phương thức này khi ứng dụng của chúng ta có sử dụng đến các luồng (thread) chạy ngầm vì chúng sẽ ngốn rất nhiều tài nguyên kể cả khi chúng ta đã thoát ứng dụng chính. Ví dụ:

@Override
public void onDestroy() {
    super.onDestroy();  
    android.os.Debug.stopMethodTracing();
}

Tạm dừng Activity

Đôi khi một màn hình giao diện của một Activity sẽ bị che khuất một phần bởi các thành phần khác như hộp thoại thông báo… lúc này Activity sẽ chuyển sang trạng thái Paused được gọi bởi phương thức onPause(), một phần của Activity vẫn hiện ra trên màn hình nhưng không xử lý tương tác với người dùng. Khi người dùng quay trở lại Activity thì hệ thống sẽ gọi phương thức onResume()Activity sẽ quay lại trạng thái Resumed. 

Thông thường khi Activity ở trạng thái Paused tức là sau đó người dùng sẽ thoát luôn chứ không phải là quay lại nữa, do đó chúng ta nên làm một số công việc như xóa tài nguyên, lưu dữ liệu đang làm việc dang dở…v.v ở phương thức này. Ví dụ:

@Override
public void onPause() {
    super.onPause();

    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

Những công việc thực hiện trong phương thức onPause() nên được đơn giản hóa và không phức tạp để tăng tốc cho ứng dụng.

Khôi phục Activity

Activity sẽ được khôi phục từ trạng thái Paused sang Resumed từ phương thức onResume().

Hệ điều hành sẽ gọi phương thức onResume() mỗi khi Activity hiện lên trên màn hình, kể cả lần khởi tạo đầu tiên. Chúng ta override phương thức này cho mỗi lần khởi tạo ứng dụng. Ví dụ:

@Override
public void onResume() {
    super.onResume(); 

    if (mCamera == null) {
        initializeCamera(); 
    }
}

Dừng Activity

Activity sẽ chuyển sang trạng thái Stopped (dừng) khi phương thức onStop() được gọi, lúc này Activity không còn hiện hữu trên màn hình, ở trong phương thức này chúng ta sẽ thực hiện giải phóng tài nguyên giống như trong phương thức onPause(). Trong một số trường hợp, hệ điều hành có thể hủy ứng dụng mà không gọi tới phương thức onStop(), do đó chúng ta cũng nên override lại phương thức này đề phòng hao tổn bộ nhớ.

Phương thức onStop() được gọi sau phương thức onPause() nhưng hầu hết chúng ta sẽ thực hiện các công việc dọn dẹp và lưu trữ nhiều hơn trong phương thức onStop() như ghi dữ liệu đang làm việc vào cơ sở dữ liệu…v.v. Ví dụ:

@Override
protected void onStop() {
    super.onStop();

    ContentValues values = new ContentValues();
    values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
    values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());

   getContentResolver().update(
        mUri, 
        values, 
        null, 
        null
   );
}

Khi Activity đi vào trạng thái Stopped, đối tượng Activity vẫn không bị xóa mà còn nằm trong bộ nhớ và có thể được phục hồi nên chúng ta có thể không cần phải khởi tạo lại những thành phần không bị xóa. Hệ điều hành thậm chí còn lưu lại trạng thái của từng View, giả sử như người dùng nhập text vào một EditText, đoạn text đó sẽ được lưu lại và khi phục hồi Activity thì đoạn text đó cũng sẽ được phục hồi.

Khởi động/khởi động lại Activity

Khi Activity được tạo ra lần đầu tiên, hệ điều hành sẽ gọi đến phương thức onCreate→onStart()→onResume(), khi Activity được khôi phục từ trạng thái Stopped, hệ điều hành sẽ gọi đến phương thức onRestart()→onStart()→onResume().

Phương thức onRestart() được gọi khi Activity được khôi phục, do đó chúng ta có thể chỉ cần khởi tạo lại những thành phần mà không bị xóa. Nhưng thông thường thì trong phương thức onStop() chúng ta sẽ xóa gần như toàn bộ mọi thứ nên phương thức onRestart()onStart() sẽ phải khởi tạo lại tất cả mọi thứ, do đó việc override phương thức onRestart() cũng không cần thiết lắm.

Ví dụ:

@Override
protected void onStart() {
    super.onStart();
 
    LocationManager locationManager = 
    (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
 
    if (!gpsEnabled) {
        ... 
    }
}

@Override
protected void onRestart() {
    super.onRestart();
 
}

Sau khi hệ điều hành đã hủy Activity, phương thức onDestroy() sẽ được gọi nhưng thường thì chúng ta cũng không làm việc với phương thức này vì hầu như toàn bộ công việc dọn dẹp sẽ được thực hiện trong phương thức onStop(). Tuy nhiên nếu muốn bạn có thể override luôn và phương thức onDestroy() là phương thức cuối cùng để chúng ta thực hiện giải phóng tài nguyên, nên bạn cũng cần chắc chắn là đã xóa tất cả mọi thứ đề phóng trường hợp thất thoát tài nguyên.

0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments