Activity Lifecycle
1. Giới thiệu
Khi một Activity được khởi chạy, nó sẽ trải qua một loạt các bước từ khởi tạo đến hiển thị và cuối cùng bị hủy. Quá trình này được gọi là Activity Lifecycle (Vòng đời của Activity).
Activity class cung cấp một bộ 6 callbacks cốt lõi để điều hướng chuyển đổi giữa các giai đoạn:
onCreate(),onStart(),onResume(),onPause(),onStop(),onDestroy()
Hệ thống gọi mỗi callback này khi Activity chuyển sang trạng thái mới.
2. Sơ đồ Activity Lifecycle
UML Sequence Diagram
Khi người dùng rời khỏi Activity, hệ thống gọi các methods để “tháo dỡ” Activity. Trong một số trường hợp, Activity chỉ bị tháo dỡ một phần và vẫn nằm trong bộ nhớ (khi chuyển sang app khác). Activity có thể quay lại foreground.
3. Các Lifecycle Callbacks
Tùy thuộc vào độ phức tạp của Activity, bạn có thể không cần implement tất cả các lifecycle methods. Tuy nhiên, việc hiểu mỗi method rất quan trọng để app hoạt động đúng như người dùng mong đợi.
onCreate()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Khôi phục instance state
gameState = savedInstanceState?.getString(GAME_STATE_KEY)
// Set layout cho activity
setContentView(R.layout.main_activity)
// Hoặc với Jetpack Compose
setContent {
MainScreen()
}
}Bạn phải implement callback này. Nó được gọi khi hệ thống tạo Activity lần đầu. Khi Activity được tạo, nó chuyển sang trạng thái Created.
Những việc thường làm trong onCreate():
- Thực hiện logic khởi tạo cơ bản chỉ xảy ra một lần trong suốt vòng đời
- Bind data vào lists
- Associate activity với
ViewModel - Khởi tạo các class-scope variables
Activity không ở lại trạng thái Created. Sau khi onCreate() kết thúc, Activity chuyển sang trạng thái Started và hệ thống gọi onStart() và onResume() ngay sau đó.
Về savedInstanceState parameter:
- Là một
Bundleobject chứa trạng thái đã lưu trước đó của Activity - Nếu Activity chưa từng tồn tại trước đó, giá trị là
null
onStart()
override fun onStart() {
super.onStart()
// Activity hiển thị cho người dùng
// Khởi tạo code duy trì UI
}Khi Activity chuyển sang trạng thái Started, hệ thống gọi onStart().
Callback này làm cho Activity hiển thị với người dùng khi app chuẩn bị để Activity vào foreground và trở nên tương tác. Đây là nơi code duy trì UI được khởi tạo.
Method onStart() hoàn thành nhanh chóng. Activity không ở lại trạng thái Started - ngay khi callback kết thúc, Activity chuyển sang trạng thái Resumed và gọi onResume().
onResume()
override fun onResume() {
super.onResume()
// Activity ở foreground và tương tác với người dùng
// Khởi tạo camera, sensors, etc.
}Khi Activity chuyển sang trạng thái Resumed, nó vào foreground và hệ thống gọi onResume(). Đây là trạng thái mà app tương tác với người dùng.
App ở lại trạng thái này cho đến khi có sự kiện khiến nó mất focus, ví dụ:
- Nhận cuộc gọi điện thoại
- Người dùng chuyển sang Activity khác
- Màn hình tắt
Nếu Activity quay lại trạng thái Resumed từ Paused, hệ thống gọi lại onResume(). Vì vậy, implement onResume() để khởi tạo các components mà bạn release trong onPause().
onPause()
override fun onPause() {
super.onPause()
// Tạm dừng hoặc điều chỉnh các operations
// Release system resources như GPS, sensors
}Hệ thống gọi method này như dấu hiệu đầu tiên rằng người dùng đang rời khỏi Activity (không phải lúc nào cũng có nghĩa Activity bị destroy).
Các lý do Activity vào trạng thái Paused:
- Có cuộc gọi điện thoại đến - màn hình cuộc gọi hiển thị đè lên app của bạn
- Người dùng mở một dialog - ví dụ: dialog xin quyền (permission), dialog chọn ảnh, hoặc AlertDialog
- Multi-window mode - khi màn hình chia đôi, chỉ app đang được chạm vào có focus, app còn lại ở trạng thái Paused
- Activity bán trong suốt hiển thị - ví dụ: bottom sheet, popup menu, hoặc activity với theme trong suốt
KHÔNG sử dụng onPause() để lưu dữ liệu app/user, network calls, hoặc database transactions. Những công việc này có thể không hoàn thành trước khi method kết thúc. Thay vào đó, thực hiện các heavy-load shutdown operations trong onStop().
onStop()
override fun onStop() {
super.onStop()
// Activity không còn hiển thị
// Pause animations, lưu data vào database
}Khi Activity không còn hiển thị cho người dùng, nó chuyển sang trạng thái Stopped và hệ thống gọi onStop().
Điều này xảy ra khi:
- Activity mới được launch che toàn bộ màn hình
- Activity hoàn thành chạy và sắp bị terminate
Những việc nên làm trong onStop():
- Release hoặc điều chỉnh resources không cần thiết khi app không hiển thị
- Pause animations
- Chuyển từ fine-grained sang coarse-grained location updates
- Lưu thông tin vào database (nếu không tìm được thời điểm tốt hơn)
Sử dụng onStop() thay vì onPause() để các UI-related work tiếp tục, ngay cả khi người dùng xem Activity trong multi-window mode.
onDestroy()
override fun onDestroy() {
super.onDestroy()
// Release tất cả resources
// Cleanup final
}onDestroy() được gọi trước khi Activity bị destroy. Hệ thống gọi callback này vì một trong hai lý do:
- Activity đang kết thúc (người dùng dismiss hoàn toàn hoặc
finish()được gọi) - Hệ thống tạm thời destroy Activity do configuration change (xoay màn hình, multi-window mode)
Thay vì đặt logic trong Activity để xác định tại sao nó bị destroy, hãy sử dụng ViewModel để chứa view data. Nếu Activity được recreate do configuration change, ViewModel được bảo tồn và truyền cho Activity instance mới.
onRestart()
override fun onRestart() {
super.onRestart()
// Từ Stopped -> Started
}Được gọi khi Activity restart từ trạng thái Stopped, ngay trước onStart().
Phân biệt restart và recreate:
- Restart: Activity từ background quay lại foreground →
onRestart()được gọi - Recreate: Configuration change (xoay màn hình) → Activity bị destroy và tạo mới →
onRestart()KHÔNG được gọi
4. Ví dụ đầy đủ
class MainActivity : ComponentActivity() {
private var gameState: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Khôi phục instance state
gameState = savedInstanceState?.getString(GAME_STATE_KEY)
setContent {
MainScreen()
}
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart - Activity visible")
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume - Activity interactive")
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause - Activity losing focus")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop - Activity not visible")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy - Activity destroyed")
}
override fun onRestart() {
super.onRestart()
Log.d(TAG, "onRestart - Activity restarting")
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putString(GAME_STATE_KEY, gameState)
super.onSaveInstanceState(outState)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
gameState = savedInstanceState.getString(GAME_STATE_KEY)
}
companion object {
private const val TAG = "MainActivity"
private const val GAME_STATE_KEY = "game_state"
}
}5. Các tình huống phổ biến
Mở Activity mới
Activity A: onPause()
Activity B: onCreate() -> onStart() -> onResume()
Activity A: onStop()Nhấn Back từ B về A
Activity B: onPause()
Activity A: onRestart() -> onStart() -> onResume()
Activity B: onStop() -> onDestroy()Xoay màn hình (Configuration Change)
onPause() -> onStop() -> onDestroy()
onCreate() -> onStart() -> onResume()Nhấn Home
onPause() -> onStop()Quay lại từ Home
onRestart() -> onStart() -> onResume()6. Lưu trữ và Khôi phục Instance State
Sử dụng onSaveInstanceState
override fun onSaveInstanceState(outState: Bundle) {
outState.putString(GAME_STATE_KEY, gameState)
outState.putInt(SCORE_KEY, score)
super.onSaveInstanceState(outState)
}Khôi phục trong onCreate hoặc onRestoreInstanceState
// Cách 1: Trong onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
gameState = savedInstanceState?.getString(GAME_STATE_KEY)
}
// Cách 2: Trong onRestoreInstanceState (chỉ gọi khi có saved state)
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
gameState = savedInstanceState.getString(GAME_STATE_KEY)
}rememberSaveable trong Compose
@Composable
fun Counter() {
var count by rememberSaveable { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}7. ViewModel survive Configuration Change
class MainViewModel : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
// ViewModel survive configuration changes
// Data không bị mất khi xoay màn hình
override fun onCleared() {
super.onCleared()
// Cleanup khi ViewModel bị destroy
}
}
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val state by viewModel.uiState.collectAsState()
MainScreen(state)
}
}
}8. Lifecycle với Compose
@Composable
fun MyScreen() {
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_RESUME -> {
Log.d("MyScreen", "Screen resumed")
}
Lifecycle.Event.ON_PAUSE -> {
Log.d("MyScreen", "Screen paused")
}
else -> {}
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}9. Best Practices
// ✅ Khởi tạo nhanh trong onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { ... } // Chỉ setup UI
}
// ✅ Khởi tạo camera/sensors trong onResume
override fun onResume() {
super.onResume()
cameraManager.startPreview()
}
// ✅ Release resources trong onPause (cho resources cần release sớm)
override fun onPause() {
super.onPause()
cameraManager.stopPreview()
}
// ✅ Heavy operations trong onStop
override fun onStop() {
super.onStop()
saveDataToDatabase()
}
// ❌ Tránh heavy work trong onPause - có thể không hoàn thành
// ❌ Tránh network calls trong lifecycle callbacks
// Dùng ViewModel + Coroutines thay thế📝 Tóm tắt
| Callback | Trạng thái | Khi nào | Việc cần làm |
|---|---|---|---|
onCreate() | Created | Activity được tạo lần đầu | Setup UI, bind data, init ViewModel |
onStart() | Started | Activity hiển thị | Init code duy trì UI |
onResume() | Resumed | Activity interactive | Start camera, sensors |
onPause() | Paused | Activity mất focus | Pause operations, release sensors |
onStop() | Stopped | Activity không hiển thị | Save data, heavy cleanup |
onDestroy() | Destroyed | Activity bị hủy | Release all resources |
onRestart() | (transitional) | Từ Stopped → Started | Refresh data nếu cần |
📚 Tham khảo: Android Developers - Activity Lifecycle