onStop — một phương thức của vòng đời Activity trong Android, được hệ thống gọi khi Activity không còn hiển thị với người dùng. Activity chuyển sang trạng thái Stopped sau khi một Activity mới che phủ hoàn toàn nó, hoặc khi ứng dụng được thu nhỏ. Trong phương thức onStop, nhà phát triển phải dừng hoạt ảnh, giải phóng tài nguyên máy ảnh và cảm biến, lưu bản nháp dữ liệu đã nhập. Theo Android Vitals (Google, 2025), xử lý onStop đúng cách giảm số lượng ANR (Ứng dụng không phản hồi) khi thu nhỏ ứng dụng xuống 35%. Sau onStop, hệ thống có thể gọi onRestart (quay lại màn hình) hoặc onDestroy (kết thúc hoàn toàn). Tài liệu Android Developers về vòng đời Activity mô tả onStop là ranh giới giữa trạng thái hiển thị và không hiển thị.
Những điểm chính
onStop — một phương thức callback của lớp AppCompatActivity (và lớp tiền nhiệm Activity), được hệ điều hành Android gọi khi Activity không còn hiển thị hoàn toàn cho người dùng. Tại thời điểm này, Activity bị ẩn bởi một Activity khác, cửa sổ hội thoại, trình khởi chạy hệ thống hoặc màn hình khóa. Từ góc nhìn vòng đời, onStop theo sau onPause và báo hiệu rằng Activity không còn hiển thị trên màn hình, mặc dù đối tượng Activity và trạng thái của nó vẫn còn trong bộ nhớ.
Khi Activity chuyển sang trạng thái Stopped (đã dừng), nó giữ trạng thái trong RAM — tất cả các trường, phân cấp View và ViewModel vẫn có thể truy cập được. Điều này phân biệt Stopped với trạng thái Destroyed (đã hủy), nơi Activity bị xóa hoàn toàn. Giao diện hệ thống có thể tiến trình ứng dụng ở trạng thái Stopped khi thiếu bộ nhớ — đây gọi là tiến trình bị hủy. Nhà phát triển phải lưu dữ liệu quan trọng (bản nháp, vị trí cuộn) trong onSaveInstanceState(), được gọi trước onStop, để đảm bảo khôi phục khi tiến trình bị hủy.
Theo Tài liệu Định nghĩa Tương thích Android (CDD) cho phiên bản 14+, một tiến trình ở trạng thái Stopped có mức ưu tiên thấp hơn để bị OOM Killer hủy — thấp hơn tiến trình trong giai đoạn Nền, nhưng cao hơn tiến trình được lưu trong bộ nhớ đệm. Theo thống kê của Google, 68% trường hợp tiến trình bị hủy xảy ra khi Activity ở trạng thái Stopped, không phải Paused.
onStop được gọi khi Activity mất hoàn toàn khả năng hiển thị, bất kể lý do: khởi chạy Activity mới phía trên Activity hiện tại, thu nhỏ ứng dụng (nhấn Home), khóa màn hình, cuộc gọi đến hoặc mở hộp thoại hệ thống. Trong tất cả các trường hợp này, Activity trước tiên nhận onPause (mất tiêu điểm một phần), sau đó onStop (mất hoàn toàn khả năng hiển thị).
Các kịch bản chính gọi onStop:
Điều quan trọng là hiểu rằng onStop không được gọi khi xoay màn hình — trong trường hợp này, Activity bị hủy (onPause → onStop → onDestroy) và được tạo lại (onCreate → onStart → onResume). Ngoại lệ là cờ android:configChanges="orientation" trong tệp kê khai, ngăn không cho Activity được tạo lại và thay vào đó gọi onConfigurationChanged().
onStop chiếm vị trí trung tâm trong chuỗi vòng đời Activity giữa trạng thái hiển thị và không hiển thị. Chuỗi đầy đủ: onCreate → onStart → onResume → (trạng thái hoạt động) → onPause → onStop → onDestroy (hoặc onRestart → onStart → onResume khi quay lại).
| Trạng thái | Phương thức | Hiển thị | Tương tác | Bộ nhớ |
|---|---|---|---|---|
| Created | onCreate | Không | Không | Được cấp phát |
| Started | onStart | Một phần | Không | Đầy đủ |
| Resumed | onResume | Đầy đủ | Có | Đầy đủ |
| Paused | onPause | Một phần | Không | Đầy đủ |
| Stopped | onStop | Không | Không | Đầy đủ* |
| Destroyed | onDestroy | Không | Không | Đã giải phóng |
*Ở trạng thái Stopped, Activity được giữ trong bộ nhớ nhưng có thể bị hệ thống hủy khi thiếu tài nguyên. Mức ưu tiên hủy tiến trình Stopped là thứ hai từ cuối, chỉ trên các tiến trình trống được lưu trong bộ nhớ đệm.
onStop và onSaveInstanceState: Hệ thống gọi onSaveInstanceState(Bundle) trước onStop để lưu trạng thái giao diện động. Nhà phát triển ghi đè phương thức này để lưu giá trị trường nhập liệu, vị trí RecyclerView và các mục đã chọn vào Bundle. Ngay cả khi Activity không bị hủy (người dùng chỉ thu nhỏ và quay lại), Bundle được chuyển đến onCreate khi thay đổi cấu hình. Google khuyến nghị chỉ lưu trạng thái giao diện tạm thời — không phải dữ liệu kho lưu trữ hoặc ViewModel, những thứ tồn tại bên ngoài Activity.
Trong onStop, nhà phát triển phải giải phóng tất cả tài nguyên không cần thiết khi Activity không hiển thị. Điều này giảm tải cho pin, CPU và bộ nhớ, đồng thời ngăn ANR khi quay lại Activity.
Những gì cần giải phóng trong onStop:
Không nên làm gì trong onStop: Không thực hiện các thao tác kéo dài — lưu lượng lớn dữ liệu vào cơ sở dữ liệu, yêu cầu mạng, tính toán phức tạp. onStop chạy trên luồng chính và chặn việc quay lại Activity. Đối với các thao tác kéo dài, hãy sử dụng WorkManager có độ trễ hoặc coroutine trong viewModelScope. Không giải phóng tài nguyên ViewModel — ViewModel tồn tại sau onStop và sẽ được sử dụng khi quay lại.
onPause và onStop khác nhau về mức độ mất khả năng hiển thị và phạm vi các hành động bắt buộc. onPause được gọi khi mất tiêu điểm một phần (ví dụ: mở cửa sổ hội thoại hoặc menu hệ thống), onStop — khi mất hoàn toàn khả năng hiển thị. Sự khác biệt này rất quan trọng để chọn tài nguyên cần giải phóng ở mỗi giai đoạn.
| Đặc điểm | onPause | onStop |
|---|---|---|
| Mức hiển thị | Hiển thị một phần | Hoàn toàn không hiển thị |
| Tiêu điểm | Đã mất | Đã mất |
| Thời gian thực thi | Lên đến 500 ms | Lên đến 5 giây (thời gian chờ ANR) |
| Tài nguyên cần giải phóng | Quan trọng (phương tiện, máy ảnh) | Tất cả không hiển thị (cảm biến, hoạt ảnh, vị trí) |
| Khôi phục | onResume | onRestart → onStart → onResume |
| Mức ưu tiên tiến trình | Cao (Tiền cảnh) | Trung bình (Nền) |
Nguyên tắc chung: trong onPause, giải phóng tài nguyên hệ thống ảnh hưởng ngay lập tức đến trải nghiệm người dùng của ứng dụng khác (máy ảnh, trình phát đa phương tiện); trong onStop — tất cả tài nguyên khác không cần thiết khi Activity bị ẩn. Google khuyến nghị lưu dữ liệu người dùng quan trọng (bản nháp email, cài đặt) trong onPause, vì onStop có thể không được gọi trong quá trình chuyển đổi nhanh.
Khi người dùng quay lại Activity bị ẩn, hệ thống gọi onRestart → onStart → onResume. Phương thức onRestart báo hiệu rằng Activity đang quay lại từ trạng thái Stopped. Đây là giai đoạn quan trọng để khôi phục giao diện và tài nguyên đã được giải phóng trong onStop.
Chuỗi lệnh gọi khi quay lại:
Nếu tiến trình ứng dụng bị hệ thống hủy ở trạng thái Stopped, onCreate được gọi thay vì onRestart, và Bundle từ onSaveInstanceState được chuyển để khôi phục trạng thái. Kịch bản này (tiến trình bị hủy) là một trong những nguyên nhân phổ biến nhất gây lỗi trong ứng dụng Android: nhà phát triển triển khai onRestart nhưng quên xem xét khôi phục qua onCreate sau khi tiến trình bị hủy.
Thể hiện việc hủy đăng ký cảm biến đúng cách và dừng hoạt ảnh khi ẩn Activity. Khi quay lại màn hình, tài nguyên được khôi phục trong onStart.
class MainActivity : AppCompatActivity() {
private lateinit var sensorManager: SensorManager
private var accelerometer: Sensor? = null
private var rotationAnimator: ObjectAnimator? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
override fun onStart() {
super.onStart()
accelerometer?.let {
sensorManager.registerListener(sensorListener, it, SensorManager.SENSOR_DELAY_NORMAL)
}
rotationAnimator = ObjectAnimator.ofFloat(findViewById(R.id.icon), "rotation", 0f, 360f)
rotationAnimator?.apply {
duration = 3000
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
start()
}
}
override fun onStop() {
super.onStop()
sensorManager.unregisterListener(sensorListener)
rotationAnimator?.cancel()
}
override fun onRestart() {
super.onRestart()
Log.d("MainActivity", "Activity quay lại từ trạng thái Stopped")
}
private val sensorListener = SensorEventListener { event, _ ->
Log.d("MainActivity", "Gia tốc: x=${event.values[0]}, y=${event.values[1]}, z=${event.values[2]}")
}
}
Mã đăng ký cảm biến gia tốc kế và bắt đầu hoạt ảnh xoay vô hạn trong onStart. Trong onStop, cảm biến được hủy đăng ký và hoạt ảnh bị hủy — điều này ngăn tiêu hao pin khi Activity bị ẩn. Sau khi quay lại qua onRestart → onStart, tài nguyên được tạo lại.
Cách tiếp cận hiện đại sử dụng ViewModel + SavedStateHandle. Dữ liệu biểu mẫu được tự động lưu trong onStop mà không cần xử lý Bundle thủ công.
class FormViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
var email: String
get() = savedStateHandle["email"] ?: ""
set(value) { savedStateHandle["email"] = value }
var message: String
get() = savedStateHandle["message"] ?: ""
set(value) { savedStateHandle["message"] = value }
}
class FormActivity : AppCompatActivity() {
private val viewModel: FormViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_form)
Log.d("FormActivity", "onCreate: email=${viewModel.email}")
}
override fun onStop() {
super.onStop()
Log.d("FormActivity", "onStop: dữ liệu đã lưu trong SavedStateHandle")
}
}
SavedStateHandle tự động lưu giá trị vào Bundle trong onSaveInstanceState, được gọi trước onStop. Khi xoay màn hình hoặc tiến trình bị hủy, dữ liệu được khôi phục mà không mất mát. Google khuyến nghị SavedStateHandle cho biểu mẫu và bản nháp thay vì onSaveInstanceState trực tiếp.
Sử dụng lifecycleScope với coroutine để lưu dữ liệu không đồng bộ trong quá trình chuyển sang onStop. Coroutine chạy trên bộ điều phối IO mà không chặn luồng chính.
class NoteActivity : AppCompatActivity() {
private val noteRepository = NoteRepository()
override fun onStop() {
lifecycleScope.launch(Dispatchers.IO) {
val text = findViewById<EditText>(R.id.note_content).text.toString()
noteRepository.saveDraft(text)
withContext(Dispatchers.Main) {
Log.d("NoteActivity", "Bản nháp đã lưu trong onStop")
}
}
super.onStop()
}
}
Coroutine lifecycleScope.launch tự động bị hủy nếu vòng đời Activity kết thúc. Sử dụng Dispatchers.IO đảm bảo rằng việc ghi vào cơ sở dữ liệu hoặc tệp không chặn việc quay lại Activity. Theo Google, coroutine trong lifecycleScope là cách ưu tiên để thực hiện các thao tác không đồng bộ trong onStop.
Các câu hỏi thường gặp
onStop — Activity không còn hiển thị nhưng vẫn ở trong bộ nhớ ở trạng thái Stopped. Hệ thống có thể đưa Activity trở lại qua onRestart. onDestroy — Activity bị hủy, bộ nhớ được giải phóng. Sau onDestroy, chỉ có thể quay lại bằng cách tạo phiên bản Activity mới (onCreate).
Có, bắt buộc. super.onStop() đảm bảo hoạt động chính xác của các thành phần hệ thống: fragment, LoaderManager, ViewModelStore. Bỏ qua super.onStop() có thể gây rò rỉ bộ nhớ và khôi phục fragment không chính xác. Luôn gọi super.onStop() ở cuối hoặc đầu — thứ tự không quan trọng, nhưng việc gọi là bắt buộc.
Sử dụng Log.d hoặc Timber trong mỗi phương thức vòng đời. Bật bộ lọc logcat theo thẻ Activity của bạn. Cho môi trường sản xuất, sử dụng Android Vitals — Google tự động thu thập số liệu vòng đời và hiển thị bất thường trong Play Console. Giám sát vòng đời cũng có sẵn qua ProcessLifecycleOwner.
Ngoại lệ không được bắt trong onStop gây ra Force Close ứng dụng. Hệ thống không bắt ngoại lệ trong callback vòng đời. Nếu onStop thực hiện các thao tác có thể ném ngoại lệ (thao tác tệp, mạng), hãy bọc chúng trong try-catch và ghi nhật ký lỗi mà không làm gián đoạn super.onStop().
Không, Bitmap trong Activity sẽ được GC thu gom nếu không có tham chiếu đến nó. Giải phóng cưỡng bức (recycle()) trong onStop là không cần thiết và thậm chí có hại — nếu Activity quay lại qua onRestart, Bitmap sẽ phải được tải lại. Sử dụng Glide hoặc Coil để tải hình ảnh — các thư viện này tự động quản lý bộ nhớ đệm và vòng đời.
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