Lifecycle của Activity
1. Giới thiệu
Phần tiêu đề “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
Phần tiêu đề “2. Sơ đồ Activity Lifecycle”flowchart TB Launched([Activity<br>launched]) onCreate["onCreate()"] onStart["onStart()"] onResume["onResume()"] Running([Activity<br>running]) onPause["onPause()"] onStop["onStop()"] onDestroy["onDestroy()"] Shutdown([Activity<br>shut down]) onRestart["onRestart()"] Killed([App process<br>killed])
Launched --> onCreate onCreate --> onStart onStart --> onResume onResume --> Running
Running --> |"Another activity comes<br>into the foreground"| onPause onPause --> |"The activity is<br>no longer visible"| onStop onStop --> |"The activity is finishing or<br>being destroyed by the system"| onDestroy onDestroy --> Shutdown
onPause --> |"User returns<br>to the activity"| onResume onStop --> |"User navigates<br>to the activity"| onRestart onRestart --> onStart
onStop --> |"Apps with higher priority<br>need memory"| Killed Killed -.-> |"User navigates<br>to the activity"| onCreate
style Launched fill:#8ecae6,stroke:#219ebc,stroke-width:2px,color:#000 style Running fill:#c5e063,stroke:#90a955,stroke-width:2px,color:#000 style Shutdown fill:#ffb703,stroke:#fb8500,stroke-width:2px,color:#000 style Killed fill:#ffb703,stroke:#fb8500,stroke-width:2px,color:#000 style onCreate fill:#e8e8e8,stroke:#999,stroke-width:1px style onStart fill:#e8e8e8,stroke:#999,stroke-width:1px style onResume fill:#e8e8e8,stroke:#999,stroke-width:1px style onPause fill:#e8e8e8,stroke:#999,stroke-width:1px style onStop fill:#e8e8e8,stroke:#999,stroke-width:1px style onDestroy fill:#e8e8e8,stroke:#999,stroke-width:1px style onRestart fill:#e8e8e8,stroke:#999,stroke-width:1pxUML Sequence Diagram
Phần tiêu đề “UML Sequence Diagram”sequenceDiagram participant System participant Activity
Note over System,Activity: Activity khởi chạy System->>Activity: onCreate() System->>Activity: onStart() System->>Activity: onResume() Note over Activity: Activity đang chạy
Note over System,Activity: User chuyển sang app khác System->>Activity: onPause() System->>Activity: onStop()
Note over System,Activity: User quay lại Activity System->>Activity: onRestart() System->>Activity: onStart() System->>Activity: onResume() Note over Activity: Activity đang chạy
Note over System,Activity: Activity bị đóng System->>Activity: onPause() System->>Activity: onStop() System->>Activity: onDestroy()3. Các Lifecycle Callbacks
Phần tiêu đề “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()
Phần tiêu đề “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
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()
Phần tiêu đề “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.
onResume()
Phần tiêu đề “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
onPause()
Phần tiêu đề “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
onStop()
Phần tiêu đề “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)
onDestroy()
Phần tiêu đề “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)
onRestart()
Phần tiêu đề “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().
4. Ví dụ đầy đủ
Phần tiêu đề “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
Phần tiêu đề “5. Các tình huống phổ biến”Mở Activity mới
Phần tiêu đề “Mở Activity mới”Activity A: onPause()Activity B: onCreate() -> onStart() -> onResume()Activity A: onStop()Nhấn Back từ B về A
Phần tiêu đề “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)
Phần tiêu đề “Xoay màn hình (Configuration Change)”onPause() -> onStop() -> onDestroy()onCreate() -> onStart() -> onResume()Nhấn Home
Phần tiêu đề “Nhấn Home”onPause() -> onStop()Quay lại từ Home
Phần tiêu đề “Quay lại từ Home”onRestart() -> onStart() -> onResume()6. Lưu trữ và Khôi phục Instance State
Phần tiêu đề “6. Lưu trữ và Khôi phục Instance State”Sử dụng onSaveInstanceState
Phần tiêu đề “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
Phần tiêu đề “Khôi phục trong onCreate hoặc onRestoreInstanceState”// Cách 1: Trong onCreateoverride 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
Phần tiêu đề “rememberSaveable trong Compose”@Composablefun Counter() { var count by rememberSaveable { mutableStateOf(0) }
Button(onClick = { count++ }) { Text("Count: $count") }}7. ViewModel survive Configuration Change
Phần tiêu đề “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
Phần tiêu đề “8. Lifecycle với Compose”@Composablefun 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
Phần tiêu đề “9. Best Practices”// ✅ Khởi tạo nhanh trong onCreateoverride fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ... } // Chỉ setup UI}
// ✅ Khởi tạo camera/sensors trong onResumeoverride 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 onStopoverride 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
Phần tiêu đề “📝 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