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().
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, Paused và Stopped. 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, Started và Destroyed 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ẻ action
và category
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()
và 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()
và 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()
và 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.