Activity Lifecycle là một tập hợp các phương thức gọi lại mà Android gọi khi Activity chuyển đổi giữa các trạng thái: tạo, hiển thị, tiêu điểm đầu vào, mất hiển thị một phần, ẩn hoàn toàn và hủy. Hệ thống quản lý vòng đời của mỗi màn hình ứng dụng, bắt đầu từ thời điểm gọi onCreate() đến onDestroy(). Hiểu các trạng thái này là yêu cầu bắt buộc để ứng dụng Android hoạt động ổn định, vì xử lý chuyển đổi không đúng giữa các phương thức dẫn đến rò rỉ bộ nhớ, mất dữ liệu người dùng và sự cố không mong muốn. Đọc thêm về kiến trúc Android trong bài viết chung về Android.
Những điểm chính
Activity Lifecycle (vòng đời Activity) là một máy trạng thái mà mỗi màn hình của ứng dụng Android trải qua từ thời điểm tạo cho đến khi hủy hoàn toàn. Hệ thống Android quản lý quá trình này dựa trên hành động của người dùng: mở ứng dụng, thu nhỏ, xoay màn hình, trả lời cuộc gọi đến, chuyển đổi giữa các ứng dụng và kết thúc.
Hiểu vòng đời là điều cần thiết cho mọi nhà phát triển Android, vì hệ thống có thể hủy Activity bất kỳ lúc nào khi thiếu bộ nhớ — và ứng dụng phải khôi phục trạng thái chính xác. Theo Google Android Vitals (2025), các ứng dụng không xử lý lưu trạng thái trong onSaveInstanceState() cho thấy 42% nhiều sự cố hơn khi tạo lại Activity.
Vòng đời bao gồm sáu phương thức gọi lại chính: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(). Ngoài ra còn có phương thức onRestart(), được gọi trước onStart() khi Activity trở về từ trạng thái dừng. Mỗi phương thức có mục đích và thời gian thực thi được xác định chặt chẽ — hệ thống gọi chúng tuần tự và nhà phát triển có thể ghi đè bất kỳ phương thức nào để thực hiện logic riêng.
Vòng đời có thể được chia thành ba giai đoạn chính: toàn bộ thời gian sống (onCreate → onDestroy), thời gian sống hiển thị (onStart → onStop) và thời gian sống ở nền trước (onResume → onPause). Hiểu ba cấp độ này giúp phân phối mã khởi tạo và giải phóng tài nguyên một cách chính xác.
Mỗi phương thức vòng đời thực hiện một tác vụ được xác định chặt chẽ. Hệ thống gọi chúng theo thứ tự cố định và nhà phát triển chỉ nên ghi đè các phương thức cần thiết cho logic cụ thể. Không khuyến nghị gọi trực tiếp các phương thức vòng đời — việc này do Android Runtime xử lý.
Trình tự điển hình khi khởi chạy ứng dụng: onCreate → onStart → onResume. Khi nhấn nút Quay lại: onPause → onStop → onDestroy. Khi thu nhỏ: onPause → onStop, sau đó khi quay lại: onRestart → onStart → onResume.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onRestart() {
super.onRestart()
}
}
Mỗi phương thức được ghi đè phải gọi phiên bản super của nó — nếu không, hệ thống không thể hoàn tất chuyển đổi trạng thái một cách chính xác. Quy tắc này được thiết lập trong tài liệu Android Developers và được kiểm tra bởi các quy tắc lint của Android Studio.
Cấp độ đầu tiên — toàn bộ thời gian sống: khoảng giữa onCreate và onDestroy. Tại đây thực hiện khởi tạo một lần và giải phóng tài nguyên toàn cục cuối cùng. Cấp độ thứ hai — thời gian sống hiển thị: giữa onStart và onStop. Activity hiển thị trên màn hình nhưng có thể bị che một phần bởi cửa sổ khác. Cấp độ thứ ba — thời gian sống ở nền trước: giữa onResume và onPause. Activity ở đầu ngăn xếp tác vụ và tương tác với người dùng.
onCreate() — phương thức đầu tiên và duy nhất bắt buộc của vòng đời Activity. Nó được hệ thống gọi một lần khi tạo phiên bản Activity. Phương thức này chấp nhận tham số savedInstanceState: Bundle?, chứa trạng thái đã lưu trước đó nếu Activity được tạo lại sau khi hủy — ví dụ: khi xoay màn hình.
Bên trong onCreate, các tác vụ sau được thực hiện: khởi tạo giao diện người dùng qua setContentView() với tài nguyên bố cục, liên kết các phần tử View qua findViewById(), thiết lập bộ điều hợp cho RecyclerView và ViewPager, khôi phục trạng thái từ savedInstanceState, khởi tạo ViewModel và LiveData, thiết lập trình lắng nghe nhấp và cử chỉ. Phương thức phải hoàn thành càng nhanh càng tốt — các thao tác dài ở đây chặn việc hiển thị khung hình đầu tiên, làm tăng thời gian khởi động ứng dụng.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
val userNameText: TextView = findViewById(R.id.user_name)
val loadButton: Button = findViewById(R.id.load_button)
if (savedInstanceState != null) {
userNameText.text = savedInstanceState.getString("user_name")
}
loadButton.setOnClickListener {
loadUserProfile()
}
}
Nếu Activity được tạo lần đầu tiên, savedInstanceState là null. Khi được tạo lại sau khi xoay màn hình, Bundle chứa dữ liệu được lưu trong onSaveInstanceState(). Kiểm tra null là thực hành tiêu chuẩn để khôi phục UI chính xác mà không mất dữ liệu người dùng đã nhập.
onStart() được gọi ngay sau onCreate() hoặc sau onRestart(), khi Activity trở nên hiển thị với người dùng. Ở trạng thái này, Activity chưa ở nền trước và không thể tương tác với người dùng, nhưng giao diện người dùng của nó đã hiển thị trên màn hình. Ví dụ: khi khởi chạy ứng dụng, hệ thống hiển thị khung hình đầu tiên của giao diện giữa các lần gọi onStart và onResume.
Trong phương thức onStart, các hành động sau thường được thực hiện: bắt đầu hoạt ảnh nên chạy khi Activity hiển thị; liên kết BroadcastReceiver; kết nối đến dịch vụ định vị và cảm biến; cập nhật dữ liệu từ ViewModel hoặc Room. Liên kết đến Bound services qua bindService() cũng được thực hiện ở đây nếu ứng dụng sử dụng kiến trúc máy khách-máy chủ trong tiến trình.
override fun onStart() {
super.onStart()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
5000L,
10f,
locationListener
)
}
override fun onStop() {
super.onStop()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.removeUpdates(locationListener)
}
Quy tắc quan trọng: tài nguyên được kết nối trong onStart phải được giải phóng trong onStop. Điều này đảm bảo rằng khi Activity không hiển thị trên màn hình, nó không tiêu thụ pin và tài nguyên hệ thống. Google Play Store kiểm tra ứng dụng về rò rỉ LocationListener và các dịch vụ hệ thống khác khi kiểm duyệt bản cập nhật.
onResume() — trạng thái Activity ở nền trước và sẵn sàng tương tác với người dùng. Đây là trạng thái làm việc của màn hình: hệ thống chuyển tiêu điểm đầu vào cho Activity, và tất cả sự kiện chạm, nhập bàn phím và cử chỉ được hướng đến màn hình này. Phương thức onResume được gọi mỗi khi Activity quay lại nền trước — sau khi Activity khác kết thúc, sau khi hộp thoại đóng, hoặc sau khi mở khóa thiết bị.
Trong onResume thực hiện: tiếp tục hoạt ảnh đã tạm dừng trong onPause; mở camera và các tài nguyên độc quyền khác; đăng ký trình lắng nghe cảm biến (gia tốc kế, con quay hồi chuyển); bắt đầu bộ đếm thời gian và đồng hồ bấm giờ cho UI; cập nhật nội dung màn hình với dữ liệu hiện tại. Cặp onResume/onPause được sử dụng cho các tài nguyên chỉ nên hoạt động khi có tiêu điểm — ví dụ: nhận dạng giọng nói liên tục hoặc chụp video.
override fun onResume() {
super.onResume()
cameraHolder.openCamera()
animator.resume()
sensorManager.registerListener(
stepCounter,
sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onPause() {
super.onPause()
cameraHolder.closeCamera()
animator.pause()
sensorManager.unregisterListener(stepCounter)
}
Sự khác biệt giữa onStart và onResume là đáng kể: Activity có thể hiển thị (onStart) nhưng không hoạt động (onResume) — ví dụ: khi hộp thoại bật lên hoặc màn hình khóa trong suốt được hiển thị phía trên. Chính trong onResume, không phải onStart, các tài nguyên độc quyền cần truy cập độc quyền nên được mở.
onPause() được gọi khi Activity mất tiêu điểm đầu vào nhưng vẫn hiển thị một phần. Các kịch bản điển hình: mở hộp thoại, nhấn nút Ứng dụng gần đây, cuộc gọi đến, nhấn nút Trang chủ (trong trường hợp này onPause sẽ được theo sau bởi onStop). Phương thức onPause là nơi đáng tin cậy cuối cùng để lưu dữ liệu mà người dùng không nên mất.
Trong onPause thực hiện: lưu bản nháp email và biểu mẫu nhập vào Room hoặc SharedPreferences; dừng hoạt ảnh và phát video; đóng camera và giải phóng tài nguyên độc quyền; hủy các thao tác tốn kém không quan trọng trong nền. Phương thức onPause phải hoàn thành trong ít hơn 100 mili giây — hệ thống chặn chuyển đổi sang Activity tiếp theo cho đến khi onPause trả lại quyền điều khiển và vượt quá giới hạn dẫn đến ANR (Application Not Responding).
override fun onPause() {
super.onPause()
val editor = SharedPreferences.Manager ...
editor.putString("draft_text", draftEditText.text.toString())
editor.apply()
videoView.pause()
cameraHolder.release()
}
Quan trọng: onPause thực thi trên luồng UI, do đó bất kỳ thao tác chặn nào như ghi vào cơ sở dữ liệu qua Room với truy vấn đồng bộ phải được thay thế bằng bất đồng bộ (coroutines) hoặc thực thi trên luồng nền. Sử dụng apply() thay vì commit() cho SharedPreferences — apply ghi dữ liệu bất đồng bộ và không chặn luồng UI.
onStop() được gọi khi Activity ngừng hiển thị với người dùng. Điều này xảy ra trong các trường hợp sau: Activity bị che phủ hoàn toàn bởi Activity khác; người dùng nhấn nút Trang chủ hoặc chuyển sang ứng dụng khác; Activity đang kết thúc (sau đó onDestroy sẽ được gọi). Ở trạng thái onStop, Activity vẫn ở trong bộ nhớ và giữ tất cả các trường của nó — nó không bị hủy, nhưng cũng không hoạt động.
Trong onStop thực hiện: hủy đăng ký BroadcastReceiver đã đăng ký trong onStart; ngắt kết nối khỏi Bound services; giải phóng LocationListener, SensorListener và các trình lắng nghe hệ thống khác; dừng các thao tác nền dài không cần thiết khi ứng dụng bị ẩn; ghi trạng thái UI hiện tại vào Bundle qua onSaveInstanceState() nếu chưa thực hiện trong onPause.
override fun onStop() {
super.onStop()
unregisterReceiver(connectivityReceiver)
unbindService(serviceConnection)
if (isChangingConfigurations()) {
Log.d("Lifecycle", "Activity được tạo lại do cấu hình")
}
}
Hệ thống có thể hủy Activity ở trạng thái onStop mà không gọi onDestroy khi thiếu bộ nhớ. Do đó, tất cả dữ liệu quan trọng phải được lưu trước khi chuyển sang onStop. Cờ isChangingConfigurations() cho phép xác định liệu lệnh gọi onStop có liên quan đến xoay màn hình hay không — trong trường hợp này, Activity sẽ được tạo lại, không kết thúc.
onDestroy() — phương thức vòng đời cuối cùng được gọi trước khi hủy hoàn toàn Activity. Hệ thống gọi onDestroy trong hai trường hợp: Activity kết thúc qua finish() hoặc người dùng nhấn nút Quay lại; Activity bị hệ thống hủy do thay đổi cấu hình (ví dụ: xoay màn hình) và sẽ được tạo lại. Phương thức onDestroy cho phép dọn dẹp tài nguyên cuối cùng: hủy liên kết luồng và coroutines, đóng con trỏ và socket đã mở vĩnh viễn, giải phóng bộ nhớ gốc qua NDK.
override fun onDestroy() {
super.onDestroy()
backgroundJob.cancel()
dbHelper.close()
if (isFinishing) {
Log.d("Lifecycle", "Activity đang kết thúc vĩnh viễn")
} else {
Log.d("Lifecycle", "Activity sẽ được tạo lại")
}
}
Lưu ý quan trọng: onDestroy không được đảm bảo gọi nếu tiến trình ứng dụng bị hệ thống tiêu diệt (out-of-memory kill). Do đó, không thể dựa vào onDestroy để lưu dữ liệu — tác vụ này được giải quyết trong onPause hoặc onStop. Thuộc tính isFinishing cho phép phân biệt việc kết thúc Activity qua finish() với việc tạo lại do thay đổi cấu hình.
onRestart() được gọi trước onStart() khi Activity trở về từ trạng thái dừng (onStop) ra nền trước. Điều này xảy ra khi người dùng mở lại ứng dụng từ menu Ứng dụng gần đây hoặc quay lại Activity bằng cách nhấn Quay lại trên màn hình con. Phương thức onRestart cho phép thực thi logic khác với onCreate — ví dụ: cập nhật dữ liệu có thể đã thay đổi trong khi Activity bị ẩn.
override fun onRestart() {
super.onRestart()
refreshDataFromNetwork()
Log.d("Lifecycle", "Activity đang khởi động lại từ ngăn xếp")
}
Kịch bản điển hình: người dùng đã mở ứng dụng, chuyển sang tác vụ khác và quay lại một giờ sau. Trong onRestart, ứng dụng có thể kiểm tra tính mới của dữ liệu và, nếu đã qua nhiều thời gian, đề xuất tải lại nội dung. Điều này cải thiện trải nghiệm người dùng và giảm khả năng hiển thị thông tin lỗi thời.
Xoay màn hình là kịch bản phổ biến nhất của việc tạo lại Activity. Theo mặc định, Android hủy Activity hiện tại và tạo một Activity mới sau mỗi lần thay đổi hướng. Nếu trạng thái không được lưu, người dùng sẽ mất tất cả dữ liệu đã nhập. Android cung cấp hai cơ chế cho việc này: onSaveInstanceState() cho dữ liệu có thể tuần tự hóa và ViewModel cho dữ liệu sống sót qua thay đổi cấu hình.
onSaveInstanceState() được gọi trước khi hủy Activity để lưu trạng thái tạm thời. Dữ liệu đã lưu được truyền đến onCreate qua tham số savedInstanceState và đến phương thức onRestoreInstanceState(), được gọi sau onStart. Bundle có giới hạn kích thước — khoảng 500 KB, do đó khối lượng dữ liệu lớn (ví dụ: bitmap) được lưu qua ViewModel.
<!-- AndroidManifest.xml — cố định hướng -->
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
Cố định hướng qua android:configChanges ngăn việc tạo lại Activity, nhưng được coi là phản mẫu nếu ứng dụng cần hỗ trợ cả hai hướng. Khuyến nghị hiện đại của Google là sử dụng ViewModel kết hợp với onSaveInstanceState cho dữ liệu người dùng nhập vào UI.
Fragment có vòng đời riêng, tương tự Activity, nhưng với các phương thức bổ sung: onAttach, onCreate, onCreateView, onViewCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach. Fragment luôn tồn tại trong Activity và vòng đời của nó gắn liền với vòng đời của Activity chứa. Nếu Activity bị hủy, Fragment cũng bị hủy theo.
Sự khác biệt chính: Fragment không chỉ quản lý trạng thái thành phần mà còn quản lý hệ thống phân cấp View. Phương thức onCreateView trả về View gốc của Fragment và onDestroyView hủy hệ thống phân cấp này. Điều này cho phép Fragment sống sót qua việc tạo lại Activity khi xoay màn hình: Fragment được giữ lại và View của nó được tạo lại trong onCreateView.
class ProfileFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val avatarImage: ImageView = view.findViewById(R.id.avatar_image)
loadAvatar(avatarImage)
}
}
Hiểu sự khác biệt giữa onCreate và onCreateView là cực kỳ quan trọng: onCreate được gọi một lần trong suốt vòng đời của Fragment (ngay cả khi View được tạo lại), trong khi onCreateView được gọi mỗi khi Fragment tạo hoặc tạo lại hệ thống phân cấp View. Khởi tạo dữ liệu được thực hiện trong onCreate, trong khi liên kết UI được thực hiện trong onViewCreated.
LifecycleObserver — một thành phần của thư viện Android Jetpack cho phép phản ứng với các thay đổi vòng đời mà không ghi đè phương thức trong Activity hoặc Fragment. Thay vì sao chép mã trong mỗi phương thức vòng đời, nhà phát triển tạo một lớp riêng biệt với chú thích @OnLifecycleEvent và truyền nó cho lifecycle.addObserver().
Jetpack cũng cung cấp giao diện LifecycleOwner, được AppCompatActivity và Fragment triển khai. Bất kỳ đối tượng nào triển khai LifecycleOwner đều có thể quản lý đăng ký LiveData, coroutines qua lifecycleScope và WorkManager liên quan đến vòng đời. Đây là nền tảng của kiến trúc Android hiện đại dựa trên MVVM và Jetpack.
class MyLocationObserver(private val context: Context) : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
stopLocationUpdates()
}
}
// Trong Activity:
lifecycle.addObserver(MyLocationObserver(this))
Sử dụng DefaultLifecycleObserver đơn giản hóa việc kiểm thử, giảm trùng lặp mã và làm cho logic vòng đời có thể tái sử dụng trên các màn hình khác nhau. Đây là sự thay thế hiện đại cho việc ghi đè thủ công onStart/onStop trong mỗi Activity. Trong các ứng dụng Android do IT Sectr phát triển, chúng tôi áp dụng LifecycleObserver cho định vị, quét Bluetooth và phân tích — điều này giảm khối lượng mã boilerplate từ 30–40%.
Câu hỏi thường gặp
Nếu không gọi super.onCreate() hoặc bất kỳ phương thức super vòng đời nào khác, hệ thống sẽ ném ra ngoại lệ SuperNotCalledException và ứng dụng sẽ bị sập. Đây là yêu cầu nghiêm ngặt của Android Runtime — mỗi phương thức phải ủy quyền thực thi cho lớp cơ sở, nếu không máy trạng thái nội bộ không thể chuyển sang trạng thái tiếp theo.
Activity bị tạo lại khi xoay màn hình vì thay đổi hướng là thay đổi cấu hình thiết bị. Theo mặc định, Android hủy Activity và tạo một Activity mới để tải tài nguyên thay thế (layout-land, values-land). Để vô hiệu hóa việc tạo lại, có thể thêm thuộc tính android:configChanges trong tệp kê khai, nhưng Google khuyến nghị sử dụng ViewModel để bảo toàn dữ liệu.
Dữ liệu quan trọng được lưu trong onPause(), vì đây là phương thức cuối cùng được đảm bảo gọi trước khi ứng dụng có thể bị hệ thống tiêu diệt. Sau onStop và onDestroy, hệ thống có thể kết thúc tiến trình mà không gọi thêm phương thức nào. Cho bản nháp và dữ liệu trung gian, sử dụng SharedPreferences với apply() hoặc Room với coroutines.
onPause được gọi khi Activity mất tiêu điểm nhưng vẫn hiển thị một phần (ví dụ: hộp thoại được mở). onStop được gọi khi Activity bị ẩn hoàn toàn khỏi màn hình bởi Activity khác hoặc khi nhấn nút Trang chủ. Sự khác biệt thực tế chính: onPause là điểm cuối cùng để lưu dữ liệu, onStop là nơi giải phóng trình lắng nghe và dịch vụ hệ thống không cần thiết trong nền.
ViewModel là một thành phần Android Jetpack lưu trữ dữ liệu UI và tự động sống sót qua các thay đổi cấu hình (xoay màn hình). ViewModel không bị hủy khi Activity được tạo lại: nó tồn tại cho đến khi LifecycleOwner (Activity hoặc Fragment) kết thúc hoàn toàn. Điều này giải quyết vấn đề bảo toàn dữ liệu khi xoay màn hình mà không cần sử dụng Bundle và onSaveInstanceState. ViewModel là một yếu tố bắt buộc của kiến trúc MVVM được Google khuyến nghị.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm