onRestart — khôi phục Activity trong vòng đời

Tác giả: IT Sectr Đã đăng: 2026-03-04 Thời gian đọc: 8 phút

onRestart — một phương thức trong vòng đời Activity của Android, được hệ thống gọi trước khi Activity trở về từ trạng thái Stopped sang trạng thái Started. onRestart báo hiệu rằng một Activity, trước đó bị ẩn bởi màn hình khác hoặc được thu nhỏ xuống nền, đang trở nên hiển thị lại cho người dùng. Trong onRestart, nhà phát triển cập nhật dữ liệu cũ, tải lại danh sách và khôi phục trạng thái UI có thể đã thay đổi trong khi Activity không hiển thị. Theo Google Android Vitals (2025), các ứng dụng sử dụng onRestart để cập nhật dữ liệu cho thấy 25% ít trường hợp hiển thị thông tin không chính xác hơn khi quay lại màn hình. Tài liệu Android Developers mô tả onRestart như một bước chuẩn bị trước khi Activity xuất hiện lại trên màn hình.

Những điểm chính

  • onRestart được gọi khi một Activity trở về từ trạng thái Stopped, trước onStart và onResume.
  • onRestart không được gọi khi Activity được tạo lần đầu — chỉ khi nó được hiển thị lại sau khi bị ẩn.
  • Mục đích chính của onRestart là cập nhật dữ liệu có thể đã thay đổi trong khi Activity không hiển thị.
  • onRestart không được gọi trong quá trình process death — trong trường hợp này, Activity được tạo lại qua onCreate.
  • Sử dụng onRestart đúng cách cải thiện trải nghiệm người dùng khi đa nhiệm và chuyển đổi giữa các ứng dụng.

onRestart — bản chất của phương thức trong vòng đời Android

onRestart — một phương thức callback mà Android gọi ngay trước onStart khi một Activity trở về từ trạng thái Stopped không nhìn thấy thành trạng thái hiển thị. Phương thức này độc đáo ở chỗ nó chỉ được gọi khi Activity được hiển thị lại — trong lần tạo instance đầu tiên, trình tự bắt đầu bằng onCreate, bỏ qua onRestart. Vòng đời đầy đủ: onCreate → onStart → onResume (lần khởi chạy đầu tiên) hoặc onRestart → onStart → onResume (hiển thị sau đó).

Từ góc nhìn của hệ thống Android, onRestart là một sự tối ưu hóa cho phép Activity chuẩn bị cho việc quay trở lại: cập nhật dữ liệu từ kho lưu trữ, đồng bộ hóa trạng thái UI, kiểm tra kết nối mạng. Không giống như onResume, được gọi mỗi khi Activity nhận được tiêu điểm (bao gồm cả khi quay lại từ hộp thoại hoặc menu hệ thống), onRestart chỉ được kích hoạt trong một chu kỳ ẩn và trở về hoàn chỉnh. Điều này làm cho onRestart trở thành nơi lý tưởng cho các hoạt động cập nhật “nặng” không cần thiết trong quá trình mất tiêu điểm một phần.

Theo đặc tả vòng đời Activity của Android, khoảng thời gian giữa onStop và onRestart có thể từ vài giây (người dùng chuyển đổi nhanh) đến vài giờ (ứng dụng ở nền và người dùng quay lại). Trong thời gian này, dữ liệu trong nguồn từ xa (API, DB) có thể đã thay đổi, vì vậy onRestart là một điểm tự nhiên để kiểm tra tính cập nhật.

Khi nào onRestart được gọi: điều kiện và trình tự

onRestart chỉ được gọi khi một Activity trở về từ trạng thái Stopped, trạng thái mà Activity đã nhập sau khi onStop được gọi. Dưới đây là tất cả các kịch bản dẫn đến onRestart.

Các kịch bản gọi onRestart:

  • Quay lại từ một Activity khác — người dùng đã mở một Activity mới (ví dụ: chạm vào thông báo) và sau đó điều hướng trở lại (nhấn “Quay lại”). Ngăn xếp: MainActivity.onPause → MainActivity.onStop → SecondActivity được tạo → người dùng nhấn “Quay lại” → SecondActivity.onPause → SecondActivity.onStop → SecondActivity.onDestroy → MainActivity.onRestart → MainActivity.onStart → MainActivity.onResume.
  • Quay lại từ việc thu nhỏ — người dùng đã thu nhỏ ứng dụng (Trang chủ) và sau một thời gian quay lại. CurrentActivity.onPause → CurrentActivity.onStop → (ứng dụng ở nền) → người dùng quay lại → CurrentActivity.onRestart → CurrentActivity.onStart → CurrentActivity.onResume.
  • Quay lại từ màn hình khóa — màn hình khóa phủ lên Activity; sau khi mở khóa, Activity nhận được onRestart nếu một khoảng thời gian đáng kể đã trôi qua (hơn 5 giây).
  • Quay lại từ một ứng dụng được khởi chạy qua Intent — máy ảnh, thư viện, trình duyệt — bất kỳ ứng dụng bên thứ ba nào được khởi chạy qua startActivityForResult() hoặc ActivityResultLauncher.

Khi nào onRestart KHÔNG được gọi: trong quá trình xoay màn hình (Activity bị hủy và được tạo lại qua onCreate), khi quay lại từ hộp thoại (Activity không đi vào onStop, chỉ onPause → onResume), trong quá trình process death (Activity được tạo lại).

onRestart so với onCreate: nên chọn cái nào

onRestart và onCreate là hai cách tiếp cận khác nhau để khôi phục một Activity. Sự lựa chọn giữa chúng phụ thuộc vào việc Activity đã bị hủy hoàn toàn hay chỉ bị ẩn.

Đặc điểmonRestartonCreate
Khi nào được gọiActivity trở về từ StoppedActivity được tạo lần đầu hoặc sau khi bị hủy
Trạng thái được bảo toànCó — ViewModel và các trường còn sốngKhông — mọi thứ được tạo mới
BundleKhông được truyềnĐược truyền (savedInstanceState)
Hành động điển hìnhCập nhật dữ liệu, làm mới UIKhởi tạo View, đăng ký LiveData
Tần suất gọiMỗi lần quay lạiMột lần hoặc sau khi hủy

Quy tắc lựa chọn: thực hiện khởi tạo View và đăng ký LiveData/StateFlow trong onCreate (hoặc onViewCreated cho Fragment). Cập nhật dữ liệu, tải lại danh sách và kiểm tra trạng thái — trong onRestart. Nếu dữ liệu được tải qua ViewModel, onRestart có thể chỉ cần gọi phương thức refresh() trên ViewModel, và View sẽ đăng ký dữ liệu đã cập nhật thông qua một luồng phản ứng.

Google khuyến nghị: không sao chép logic của onCreate trong onRestart. Trích xuất các phương thức refresh() trong ViewModel để tải dữ liệu hiện tại và gọi chúng trong onRestart. Điều này duy trì kiến trúc MVVM sạch sẽ và loại bỏ trùng lặp mã.

Các kịch bản sử dụng onRestart: cập nhật dữ liệu và UI

onRestart là nơi lý tưởng cho các hoạt động nên được thực hiện mỗi khi quay lại màn hình, nhưng không cần thiết khi mở lần đầu. Dưới đây là các kịch bản điển hình:

  • Cập nhật danh sách từ DB hoặc API — người dùng đã đến một Activity khác, thay đổi dữ liệu ở đó, quay lại — danh sách phải được cập nhật. Gọi viewModel.refreshItems() trong onRestart.
  • Kiểm tra ủy quyền — nếu Activity bị ẩn trong thời gian dài, mã thông báo truy cập có thể đã hết hạn. onRestart là điểm để kiểm tra tính hợp lệ của mã thông báo và chuyển hướng đến màn hình đăng nhập.
  • Đồng bộ hóa trạng thái UI — chuyển đổi chủ đề, thay đổi ngôn ngữ, cập nhật cài đặt — các thay đổi sẽ được áp dụng khi quay lại màn hình.
  • Tải lại phương tiện — nếu Activity hiển thị nội dung có thể đã thay đổi (nguồn cấp tin tức, tỷ giá tiền tệ, thời tiết), hãy cập nhật dữ liệu trong onRestart.
  • Kiểm tra kết nối mạng — khi quay lại từ chế độ ngoại tuyến, Activity nên kiểm tra khả năng khả dụng của mạng và chuyển đổi UI.
  • Khôi phục hoạt ảnh — các hoạt ảnh được giải phóng trong onStop nên được khởi động lại trong onRestart trước onStart.

Những gì KHÔNG nên làm trong onRestart: không khởi tạo lại Views — chúng còn sống vì Activity không bị hủy. Không đăng ký lại LiveData — đăng ký trong onCreate vẫn còn hiệu lực. Không tạo Fragments mới — chúng đã có trong FragmentManager.

onRestart và process death: một ngoại lệ quan trọng

Ngoại lệ quan trọng nhất: onRestart không được gọi nếu tiến trình ứng dụng bị hệ thống tiêu diệt. Đây là điểm mấu chốt mà các nhà phát triển thường bỏ qua khi dựa vào onRestart để khôi phục trạng thái.

Trong quá trình process death:

  • Ứng dụng đang ở nền, Android đã tiêu diệt tiến trình để giải phóng bộ nhớ.
  • Người dùng quay lại — hệ thống khởi động một tiến trình mới.
  • Activity được tạo lại: onCreate(Bundle) → onStart → onResume.
  • onRestart KHÔNG được gọi — đối với hệ thống, đây là một instance Activity mới.

Cách bảo vệ chống lại điều này: luôn lưu trạng thái quan trọng trong onSaveInstanceState(Bundle) (được gọi trước onStop) hoặc sử dụng SavedStateHandle trong ViewModel. Trong onCreate, kiểm tra savedInstanceState: nếu không phải null, khôi phục trạng thái từ Bundle; nếu là null, tải dữ liệu mới.

Theo Google Android Vitals, khoảng 7% số lần quay lại Activity sau thời gian dài ở nền xảy ra sau process death. Điều này có nghĩa là cứ 15 Activity lẽ ra phải gọi onRestart thì thực tế lại đi qua onCreate. Bỏ qua kịch bản này là một trong những nguyên nhân chính gây ra lỗi “màn hình trống sau khi quay lại”.

Ví dụ mã với onRestart trong Kotlin

Ví dụ 1: onRestart với cập nhật danh sách qua ViewModel

Activity gọi viewModel.refreshTasks() trong onRestart để cập nhật danh sách tác vụ sau khi quay lại từ màn hình chỉnh sửa.

kotlin
class TaskListActivity : AppCompatActivity() {
    private val viewModel: TaskViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_task_list)
        viewModel.tasks.observe(this) { tasks ->
            Log.d("TaskList", "Đã nhận ${tasks.size} tác vụ")
        }
    }

    override fun onRestart() {
        super.onRestart()
        Log.d("TaskList", "onRestart: đang cập nhật danh sách tác vụ")
        viewModel.refreshTasks()
    }
}

class TaskViewModel : ViewModel() {
    private val _tasks = MutableLiveData<List<Task>>()
    val tasks: LiveData<List<Task>> get() = _tasks

    fun refreshTasks() {
        viewModelScope.launch {
            _tasks.value = TaskRepository().getAllTasks()
        }
    }
}

ViewModel.refreshTasks() tải dữ liệu hiện tại từ kho lưu trữ. LiveData tự động thông báo cho Activity về các thay đổi dữ liệu — UI được cập nhật mà không cần mã bổ sung. onRestart không tạo đăng ký mới — nó đã được thiết lập trong onCreate.

Ví dụ 2: onRestart với kiểm tra ủy quyền

Activity kiểm tra tính hợp lệ của mã thông báo khi quay lại và chuyển hướng đến đăng nhập nếu cần.

kotlin
class ProfileActivity : AppCompatActivity() {
    private val authManager = AuthManager()
    private val launcher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { Log.d("Profile", "Đã quay lại từ màn hình đăng nhập") }

    override fun onRestart() {
        super.onRestart()
        if (!authManager.isTokenValid()) {
            Log.d("Profile", "Mã thông báo hết hạn — đang chuyển hướng đến đăng nhập")
            launcher.launch(Intent(this, LoginActivity::class.java))
        }
    }
}

class AuthManager {
    fun isTokenValid(): Boolean {
        val expiry = SharedPreferencesManager().getTokenExpiry()
        return System.currentTimeMillis() < expiry
    }
}

Nếu người dùng đã thu nhỏ ứng dụng trong thời gian dài và quay lại sau khi mã thông báo hết hạn, onRestart sẽ chuyển hướng họ đến màn hình đăng nhập. Điều này ngăn ngừa lỗi API khi cố gắng thực hiện yêu cầu với mã thông báo đã hết hạn. Lưu ý: việc kiểm tra nằm trong onRestart, không phải onResume, để tránh kiểm tra không cần thiết khi quay lại từ hộp thoại.

Ví dụ 3: onRestart trong Fragment với ViewLifecycleOwner

Fragment sử dụng onRestart qua LifecycleObserver để cập nhật dữ liệu.

kotlin
class FeedFragment : Fragment() {
    private val viewModel: FeedViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
            @OnLifecycleEvent(Lifecycle.Event.ON_RESTART)
            fun onRestart() {
                Log.d("FeedFragment", "onRestart qua LifecycleObserver")
                viewModel.refreshFeed()
            }
        })
    }
}

Thay vì ghi đè onRestart trong Fragment, LifecycleObserver được sử dụng — một cách tiếp cận linh hoạt hơn cho phép thêm logic sự kiện vòng đời mà không cần kế thừa. ViewLifecycleOwner đảm bảo rằng observer tồn tại trong phạm vi của View (nó không tồn tại lâu hơn onDestroyView).

Các câu hỏi thường gặp

onRestart khác onResume như thế nào?

onResume được gọi mỗi khi Activity nhận được tiêu điểm — bao gồm cả khi quay lại từ hộp thoại hoặc menu hệ thống (Activity không đi vào onStop). onRestart chỉ được gọi khi quay lại từ trạng thái Stopped, khi Activity bị ẩn hoàn toàn. onRestart là một sự kiện hẹp hơn cho các cập nhật “nặng”, trong khi onResume dành cho các hoạt động nhẹ (thay đổi tiêu đề, cập nhật thời gian).

onRestart có thể được gọi mà không có onStop không?

Không, không thể. onRestart là một phương thức cặp với onStop: onRestart chỉ được gọi sau khi Activity đã đi qua onStop. Nếu Activity không đi vào onStop (ví dụ: một hộp thoại đã được mở), thì khi quay lại onRestart không được gọi — chỉ onResume.

Làm thế nào để mô phỏng onRestart trong trình giả lập?

Nhấn Home (nút trang chủ) trong trình giả lập — Activity sẽ thu nhỏ và nhận onStop. Sau đó mở ứng dụng qua Ứng dụng gần đây hoặc trình khởi chạy — Activity sẽ nhận onRestart → onStart → onResume. Để gỡ lỗi, sử dụng Debug với các điểm dừng trong onRestart hoặc Log.d với thẻ Activity.

Điều gì xảy ra nếu một ngoại lệ được ném trong onRestart?

Một ngoại lệ không được bắt trong onRestart sẽ gây ra Force Close. Hệ thống không bắt các ngoại lệ trong callback vòng đời. Nếu onRestart thực hiện các hoạt động có thể ném ngoại lệ (yêu cầu mạng không có try-catch, làm việc với View null), hãy bọc chúng trong try-catch.

Tôi có cần kiểm tra isFinishing() trong onRestart không?

Không. onRestart chỉ được gọi cho các Activity còn sống đang quay lại từ trạng thái Stopped. isFinishing() trong onRestart sẽ luôn là false. Kiểm tra isFinishing() có ý nghĩa trong onPause (lưu dữ liệu) và onDestroy (phân biệt tạo lại với kết thúc).

Tóm tắt

  • onRestart — một phương thức vòng đời được gọi khi một Activity trở về từ trạng thái Stopped, trước onStart và onResume.
  • onRestart KHÔNG được gọi khi Activity được tạo lần đầu — chỉ khi nó được hiển thị lại sau khi bị ẩn hoàn toàn.
  • Mục đích chính của onRestart là cập nhật dữ liệu cũ và kiểm tra trạng thái (mã thông báo, mạng, cài đặt).
  • onRestart không được gọi trong quá trình process death — sử dụng onCreate với Bundle để khôi phục sau process death.
  • Không sao chép logic của onCreate trong onRestart: thực hiện khởi tạo trong onCreate, cập nhật trong onRestart.
  • Đối với Fragment, sử dụng LifecycleObserver trên viewLifecycleOwner thay vì ghi đè onRestart.
  • Việc triển khai onRestart đúng cách cải thiện UX khi đa nhiệm và ngăn hiển thị dữ liệu cũ.

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.

Thảo luận dự án

Đọc thêm