onStart: bản chất, khả năng hiển thị Activity trên màn hình Android

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

onStart là một phương thức vòng đời Android được gọi khi Activity hoặc Fragment trở nên hiển thị với người dùng. Tại thời điểm này, màn hình xuất hiện trên thiết bị, nhưng chưa thể tương tác với người dùng — tiêu điểm đầu vào không có cho đến khi onResume được gọi. Phương thức onStart rất lý tưởng để đăng ký bộ lắng nghe hệ thống, kết nối với dịch vụ định vị và khởi chạy hoạt ảnh cần chạy khi thành phần hiển thị trên màn hình. Tìm hiểu thêm về vòng đời Activity đầy đủ trong bài viết Activity Lifecycle.

Những điểm chính

  • onStart — được gọi khi Activity hoặc Fragment hiển thị trên màn hình; diễn ra trước onResume
  • Đăng ký bộ lắng nghe — BroadcastReceiver, LocationListener, SensorListener đăng ký trong onStart và hủy đăng ký trong onStop
  • Hoạt ảnh — khởi chạy hoạt ảnh cần chạy khi màn hình hiển thị; tạm dừng trong onStop
  • Dịch vụ liên kết — kết nối đến dịch vụ client-server qua bindService trong onStart, ngắt kết nối trong onStop
  • onStart vs onResume — onStart = khả năng hiển thị, onResume = tiêu điểm + tương tác; các mức hoạt động màn hình khác nhau
  • Fragment.onStart — được gọi sau Activity.onStart, khi Fragment hiển thị trong container
  • Cặp onStart/onStop — tài nguyên kết nối trong onStart phải được giải phóng trong onStop để tránh rò rỉ

Bản chất của onStart trong Android

onStart là phương thức thứ hai của vòng đời Activity, được hệ thống gọi sau onCreate (hoặc sau onRestart khi quay lại từ trạng thái dừng). Tại thời điểm onStart được gọi, Activity hoặc Fragment trở nên hiển thị trên màn hình. Người dùng nhìn thấy giao diện, nhưng màn hình chưa sẵn sàng cho tương tác — tiêu điểm đầu vào sẽ chỉ xuất hiện sau onResume.

Phương thức onStart thuộc về “thời gian sống hiển thị” (visible lifetime) của Activity — khoảng thời gian giữa onStart và onStop. Trong giai đoạn này, Activity có thể bị che một phần bởi các cửa sổ khác (ví dụ: Activity trong suốt hoặc cửa sổ hội thoại), nhưng UI của nó vẫn hiển thị. Điều này phân biệt thời gian sống hiển thị với “thời gian sống tiền cảnh” (onResume — onPause), khi Activity có tiêu điểm đầu vào đầy đủ.

Hiểu được hệ thống phân cấp ba cấp này rất quan trọng để phân phối mã đúng cách. onCreate — khởi tạo một lần, onStart — kết nối tài nguyên hiển thị, onResume — truy cập độc quyền vào tài nguyên độc quyền. Nhà phát triển nhầm lẫn các cấp này có nguy cơ tạo ra rò rỉ bộ nhớ hoặc hành vi ứng dụng không chính xác khi chuyển đổi giữa các màn hình.

onStart trong Activity

Trong Activity, phương thức onStart được gọi mỗi khi màn hình xuất hiện trên thiết bị — cả khi khởi chạy lần đầu (sau onCreate) và khi quay lại từ nền (sau onRestart). Không giống như onCreate, onStart có thể được gọi nhiều lần trong suốt vòng đời của một phiên bản Activity, vì vậy mã cần thực thi mỗi khi màn hình xuất hiện được đặt ở đây.

kotlin
class DashboardActivity : AppCompatActivity() {
    private val connectivityReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val isConnected = ... // Kiểm tra ConnectivityManager
            binding?.statusIndicator?.setColor(
                if (isConnected) Color.GREEN else Color.RED
            )
        }
    }

    override fun onStart() {
        super.onStart()
        registerReceiver(
            connectivityReceiver,
            IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        )
        SensorManager.getInstance().registerStepCounter()
    }

    override fun onStop() {
        unregisterReceiver(connectivityReceiver)
        SensorManager.getInstance().unregisterStepCounter()
        super.onStop()
    }
}

Quy tắc chính: tất cả tài nguyên 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 bị ẩn khỏi màn hình, nó không tiêu thụ pin, không lắng nghe sự kiện hệ thống và không chiếm dụng bộ nhớ. Android Studio bao gồm các quy tắc lint cảnh báo về việc đăng ký BroadcastReceiver mà không hủy đăng ký tương ứng.

onStart trong Fragment

onStart trong Fragment gắn chặt với vòng đời của Activity chứa nó. Fragment nhận được lệnh gọi onStart sau khi Activity chứa nó đã nhận được onStart. Tuy nhiên, nếu Fragment được thêm ở chế độ trì hoãn (FragmentTransaction.commit() không có addToBackStack), onStart có thể được gọi với độ trễ.

kotlin
class MapFragment : Fragment() {
    private var mapView: MapView? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mapView = MapView(requireContext())
        return mapView!!
    }

    override fun onStart() {
        super.onStart()
        mapView?.onStart()
        LocationService.connect(requireContext())
    }

    override fun onStop() {
        mapView?.onStop()
        LocationService.disconnect()
        super.onStop()
    }
}

Đặc thù của Fragment.onStart: nếu Fragment nằm trong ViewPager với offscreenPageLimit = 1, các fragment lân cận cũng sẽ nhận được onStart trước khi hiển thị. Điều này có thể dẫn đến việc đăng ký bộ lắng nghe sớm. Trong những trường hợp này, hãy sử dụng phương thức setUserVisibleHint() hoặc kiểm tra isVisible bên trong onStart để chỉ đăng ký bộ lắng nghe cho các fragment thực sự hiển thị.

Sự khác biệt giữa onStart và onResume

Sự khác biệt chính giữa onStart và onResume là mức hoạt động của màn hình. onStart báo hiệu rằng Activity hiển thị trên màn hình nhưng không nhất thiết ở tiền cảnh. onResume báo hiệu rằng Activity ở tiền cảnh và có tiêu điểm đầu vào. Sự khác biệt được thể hiện qua ví dụ cửa sổ hội thoại: khi Dialog xuất hiện trên Activity, Activity mất onResume (onPause được gọi) nhưng vẫn hiển thị — onStart/onStop không được gọi.

Bảng so sánh hiển thị rõ ràng trong những kịch bản nào mỗi phương thức được gọi:

Kịch bảnonStartonResume
Khởi chạy ứng dụngĐược gọiĐược gọi
Dialog mở trên ActivityKhông được gọionPause (mất tiêu điểm)
Nhấn nút HomeonStop (ẩn)onPause → onStop
Quay lại từ Gần đâyonStart (hiển thị)onResume (tiêu điểm)
Xoay màn hìnhonCreate → onStart→ onResume
Cuộc gọi đếnonStop (ẩn)onPause → onStop

Bảng này giúp nhà phát triển quyết định nên đặt mã cụ thể vào phương thức nào. Ví dụ: nếu ứng dụng cần tạm dừng phát video khi có bất kỳ sự chồng chéo màn hình nào (kể cả hội thoại), mã được đặt trong onPause. Nếu video chỉ nên dừng khi màn hình bị ẩn hoàn toàn — mã được đặt trong onStop.

Đăng ký bộ lắng nghe và dịch vụ

onStart là nơi tối ưu để đăng ký bộ lắng nghe chỉ nên hoạt động khi Activity hiển thị trên màn hình. Điều này liên quan đến ba loại thành phần hệ thống chính: BroadcastReceiver cho sự kiện hệ thống, LocationListener cho định vị và SensorListener cho cảm biến thiết bị.

BroadcastReceiver trong onStart

BroadcastReceiver được đăng ký động qua Context.registerReceiver() trong onStart và hủy đăng ký trong onStop qua unregisterReceiver(). Đăng ký động được ưu tiên hơn đăng ký tĩnh (trong tệp kê khai) vì nó giới hạn thời gian sống của bộ thu trong khoảng thời gian hiển thị của Activity — ứng dụng không thức dậy từ các thông báo broadcast hệ thống khi Activity bị ẩn.

kotlin
private val batteryReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent) {
        val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
        binding?.batteryText?.text = "$level%"
    }
}

override fun onStart() {
    super.onStart()
    registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}

override fun onStop() {
    unregisterReceiver(batteryReceiver)
    super.onStop()
}

LocationListener và SensorListener

Định vị và cảm biến là các hoạt động tốn nhiều tài nguyên. Yêu cầu cập nhật GPS trong onStart và hủy trong onStop đảm bảo rằng ứng dụng không tiêu hao pin khi màn hình bị ẩn. Để điều chỉnh chính xác, hãy sử dụng requestLocationUpdates với khoảng thời gian và khoảng cách tối thiểu — ví dụ: 10 giây và 10 mét, mang lại sự cân bằng tối ưu giữa độ chính xác và mức tiêu thụ năng lượng.

Hoạt ảnh và onStart

Khởi chạy hoạt ảnh trong onStart, thay vì trong onCreate, đảm bảo rằng hoạt ảnh bắt đầu mỗi khi màn hình xuất hiện. Nếu bạn khởi chạy hoạt ảnh trong onCreate, nó sẽ chỉ hoạt động khi tạo Activity lần đầu, không phải khi quay lại từ nền. onStart được gọi mỗi khi Activity hiển thị, khiến nó trở thành nơi lý tưởng để khởi chạy hoạt ảnh tuần hoàn và chuyển tiếp.

kotlin
private lateinit var pulseAnimator: ValueAnimator

override fun onStart() {
    super.onStart()
    pulseAnimator.start()
    binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}

override fun onStop() {
    pulseAnimator.cancel()
    binding?.loadingIndicator?.animate()?.cancel()
    super.onStop()
}

Đối với hoạt ảnh sử dụng ObjectAnimator hoặc ValueAnimator, điều quan trọng là gọi cancel() trong onStop. Nếu hoạt ảnh tiếp tục chạy sau khi Activity bị ẩn, nó tiêu thụ tài nguyên GPU và CPU một cách vô ích, làm giảm hiệu suất thiết bị và tăng tốc độ xả pin. Android Studio Profiler (đồ thị GPU) cho phép bạn theo dõi hoạt ảnh đang hoạt động và phát hiện rò rỉ.

Quy tắc cặp onStart/onStop cũng áp dụng khi làm việc với máy ảnh để xem trước (CameraX). Mở máy ảnh trong onStart và đóng trong onStop đảm bảo rằng máy ảnh không bị chặn cho các ứng dụng khác khi ứng dụng của bạn không hiển thị trên màn hình. Vi phạm quy tắc này là một nguyên nhân phổ biến của các đánh giá tiêu cực trên Google Play.

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

Sự khác biệt giữa onStart và onResume khi đăng ký bộ lắng nghe là gì?

onStart — dành cho bộ lắng nghe cần hoạt động khi màn hình hiển thị (BroadcastReceiver, LocationListener, SensorListener). onResume — dành cho tài nguyên yêu cầu truy cập độc quyền (máy ảnh, chụp video, nhận dạng giọng nói). Bộ lắng nghe sự kiện hệ thống không yêu cầu truy cập độc quyền và có thể hoạt động với sự chồng chéo một phần — chúng được đăng ký trong onStart. Máy ảnh chỉ nên hoạt động khi có tiêu điểm đầy đủ — nó được mở trong onResume.

Tại sao onStart có thể không được gọi?

onStart luôn được gọi nếu Activity chuyển sang trạng thái hiển thị. Kịch bản duy nhất không có onStart — Activity được tạo và kết thúc ngay lập tức (ví dụ: do lỗi trong onCreate). Trong trường hợp này, onDestroy được gọi ngay sau onCreate. Nhưng đây là kịch bản khẩn cấp không nên xảy ra trong mã được viết đúng cách.

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

Có, onStart có thể không nhận được onResume nếu một Activity khác hoặc cửa sổ trong suốt mở ngay lập tức trên Activity. Ví dụ: nếu màn hình ủy quyền được khởi chạy sau onCreate (Activity A → Activity B), trong Activity A, onStart được gọi, nhưng onResume thì không — nó ngay lập tức nhận onPause → onStop khi bị che bởi màn hình B.

onStart có thể được gọi bao nhiêu lần?

onStart có thể được gọi nhiều lần trong suốt vòng đời của một phiên bản Activity. Mỗi khi Activity chuyển từ trạng thái ẩn (onStop) sang trạng thái hiển thị, onStart được gọi. Trong thực tế, khi sử dụng ứng dụng tích cực, onStart có thể được gọi hàng chục hoặc hàng trăm lần mỗi phiên.

Có nên tải dữ liệu trong onStart không?

Tải dữ liệu trong onStart là hợp lý nếu dữ liệu cần được cập nhật mỗi khi màn hình xuất hiện. Ví dụ: nguồn cấp tin tức hoặc danh sách thông báo. Tuy nhiên, việc tải phải không đồng bộ — qua coroutine với lifecycleScope, để không chặn luồng UI. Đối với dữ liệu không thay đổi giữa các lần xuất hiện màn hình, tải một lần trong onCreate là đủ.

Tổng kết

  • onStart — phương thức thời gian sống hiển thị; được gọi khi Activity hoặc Fragment xuất hiện trên màn hình
  • Đăng ký trong onStart — BroadcastReceiver, LocationListener, SensorListener đăng ký trong onStart và hủy đăng ký trong onStop
  • onStart vs onResume — onStart = khả năng hiển thị, onResume = tiêu điểm đầu vào; các cấp khác nhau cho các loại tài nguyên khác nhau
  • Hoạt ảnh — khởi chạy hoạt ảnh tuần hoàn trong onStart, dừng trong onStop; ngăn rò rỉ tài nguyên GPU
  • Fragment.onStart — liên kết với Activity.onStart; trong ViewPager được gọi trước cho các fragment lân cận
  • Quy tắc cặp — tất cả tài nguyên onStart phải được giải phóng trong onStop, nếu không sẽ rò rỉ bộ nhớ và pin
  • Tải dữ liệu — trong onStart, tải dữ liệu cần được cập nhật mỗi khi màn hình xuất hiện

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