lifecycleScope — คืออะไร การเชื่อมโยงกับ Lifecycle และการทำงานใน Android

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-23 เวลาอ่าน: 9 นาที

lifecycleScope เป็น CoroutineScope ในตัวจากไลบรารี androidx.lifecycle ที่เชื่อมโยงกับวงจรชีวิตของ Activity, Fragment หรือ LifecycleOwner ใดๆ และยกเลิก coroutine โดยอัตโนมัติเมื่อคอมโพเนนต์ถูกทำลาย ตาม Google Android Developers, 2025 lifecycleScope ช่วยให้คุณเรียกใช้ coroutine ที่เกี่ยวข้องกับเลเยอร์ UI ได้อย่างปลอดภัย โดยไม่มีความเสี่ยงที่จะเรียกใช้โค้ดหลังจาก Activity หรือ Fragment ถูกทำลาย Scope จะถูกยกเลิกโดยอัตโนมัติเมื่อ LifecycleOwner เปลี่ยนไปเป็นสถานะ DESTROYED

ประเด็นสำคัญ

  • lifecycleScope — CoroutineScope จาก lifecycle-runtime-ktx ถูกยกเลิกที่สถานะ DESTROYED ของ Lifecycle
  • lifecycleScope.launch — เริ่ม coroutine ที่ถูกยกเลิกโดยอัตโนมัติเมื่อ LifecycleOwner ถูกทำลาย
  • launchWhenStarted / launchWhenResumed — เมธอดที่เลิกใช้แล้ว ถูกแทนที่ด้วย repeatOnLifecycle
  • repeatOnLifecycle — API ที่ทันสมัยสำหรับเริ่ม coroutine ที่ติดตามสถานะเฉพาะของ Lifecycle
  • Dispatchers.Main.immediate — ตัวจัดส่งเริ่มต้นสำหรับ lifecycleScope

lifecycleScope ใน Android คืออะไร?

lifecycleScope เป็นคุณสมบัติส่วนขยายบนอินเทอร์เฟซ LifecycleOwner (Activity, Fragment, Service) ที่ให้ CoroutineScope พร้อมใช้ เชื่อมโยงกับวงจรชีวิตทั้งหมดของคอมโพเนนต์ เมื่อ LifecycleOwner ถึงสถานะ DESTROYED lifecycleScope จะยกเลิก coroutine ที่ทำงานอยู่ทั้งหมดโดยอัตโนมัติ

kotlin
// In Fragment or Activity
lifecycleScope.launch {
    delay(1000)
    showSnackbar("สวัสดี!")
}

แตกต่างจาก viewModelScope ตรงที่ lifecycleScope จะถูกยกเลิกทุกครั้งที่ LifecycleOwner ถูกทำลาย — รวมถึงการหมุนหน้าจอ ทำให้เหมาะสำหรับการดำเนินการที่ควรมีชีวิตอยู่เฉพาะเมื่อหน้าจอเฉพาะกำลังแสดงอยู่

สถานที่ที่ lifecycleScope พร้อมใช้งาน

lifecycleScope พร้อมใช้งานทุกที่มี LifecycleOwner:

  • Activity — AppCompatActivity สืบทอด LifecycleOwner
  • Fragment — Fragment สืบทอด LifecycleOwner
  • LifecycleService — บริการที่มีวงจรชีวิต
  • ProcessLifecycleOwner — วงจรชีวิตของทั้งแอปพลิเคชัน
  • LifecycleOwner ที่กำหนดเอง — วัตถุใดๆ ที่ใช้ LifecycleOwner

lifecycleScope ทำงานอย่างไร: Lifecycle และการยกเลิกอัตโนมัติ

กลไกการยกเลิกอัตโนมัติของ lifecycleScope ขึ้นอยู่กับการสมัครรับเหตุการณ์ Lifecycle เมื่อ Lifecycle ลดลงต่ำกว่า CREATED ไปยัง DESTROYED scope จะถูกยกเลิก

สถานะของ Lifecycle

สถานะคำอธิบายScope ทำงาน
CREATEDLifecycleOwner ถูกสร้างขึ้น, onCreate ถูกเรียกใช้ใช่
STARTEDLifecycleOwner มองเห็นได้ (onStart)ใช่
RESUMEDLifecycleOwner อยู่เบื้องหน้า (onResume)ใช่
DESTROYEDLifecycleOwner ถูกทำลาย (onDestroy)ไม่ (scope ถูกยกเลิก)

โครงสร้างภายในของ lifecycleScope

lifecycleScope ถูกสร้างขึ้นเป็น CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) และจัดเก็บภายใน Lifecycle เมื่อ Lifecycle เปลี่ยนไปเป็นสถานะ DESTROYED จะเรียก scope.cancel() กลไกนี้ถูกใช้งานผ่าน LifecycleEventObserver ซึ่งสมัครรับเหตุการณ์วงจรชีวิตเมื่อเข้าถึง scope ครั้งแรก

พฤติกรรมเมื่อหมุน

เมื่อหมุนหน้าจอ Activity จะถูกทำลาย (onDestroy) และสร้างใหม่ lifecycleScope จะถูกยกเลิกพร้อมกับ Activity เก่า และอินสแตนซ์ scope ใหม่จะถูกสร้างขึ้นสำหรับ Activity ใหม่ นี่คือความแตกต่างพื้นฐานจาก viewModelScope ซึ่งคงอยู่เมื่อหมุน

API ของ lifecycleScope: launch, launchWhen และ repeatOnLifecycle

ไลบรารี lifecycle มีหลายวิธีในการเริ่ม coroutine ผ่าน lifecycleScope มาดูวิวัฒนาการของ API จากเมธอดที่เลิกใช้แล้วไปจนถึงสมัยใหม่

lifecycleScope.launch — การเริ่มต้นพื้นฐาน

วิธีที่ง่ายที่สุดคือ lifecycleScope.launch { ... } coroutine เริ่มต้นทันทีและถูกยกเลิกที่ DESTROYED อย่างไรก็ตาม มันสามารถเรียกใช้โค้ดได้แม้เมื่อ UI ไม่ปรากฏ (เช่น ในพื้นหลังหลังจาก onStop) ซึ่งไม่เป็นที่ต้องการเสมอไป

เมธอดที่เลิกใช้แล้ว: launchWhenCreated / launchWhenStarted / launchWhenResumed

เมธอดเหล่านี้จะหยุดการทำงานของ coroutine ชั่วคราวเมื่อ Lifecycle ลดลงต่ำกว่าสถานะที่ระบุ และดำเนินการต่อเมื่อกลับมา อย่างไรก็ตาม พวกมันถูกทำเครื่องหมายเป็น @Deprecated ใน lifecycle-runtime-ktx 2.6.0 เพราะ:

  • พวกมันไม่ยกเลิก coroutine — แค่หยุดชั่วคราว
  • พวกมันทำให้เกิดการสะสมของ coroutine ที่ถูกระงับซึ่งกินหน่วยความจำ
  • พวกมันสร้างสภาวะการแข่งขันเมื่อเปลี่ยนสถานะอย่างรวดเร็ว

API ที่ทันสมัย: repeatOnLifecycle

repeatOnLifecycle เป็นวิธีที่ Google แนะนำในการเริ่ม coroutine ที่ซิงค์กับวงจรชีวิต มันยกเลิกและเริ่ม coroutine ใหม่ทุกครั้งที่ Lifecycle ถึงสถานะที่ระบุ

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { state ->
            updateUI(state)
        }
    }
}

coroutine ที่ส่งไปยัง repeatOnLifecycle จะเริ่มเมื่อ Lifecycle ถึง STARTED และจะถูกยกเลิกเมื่อลดลงต่ำกว่า STARTED เมื่อกลับสู่ STARTED coroutine จะเริ่มต้นใหม่ตั้งแต่ต้น ปลอดภัยและมีประสิทธิภาพ — ไม่มี coroutine ใดถูกระงับค้างอยู่

flowWithLifecycle — สำหรับ Flow

สำหรับการรวบรวมข้อมูลจาก Flow โดยรับรู้วงจรชีวิต มีโอเปอเรเตอร์ flowWithLifecycle ซึ่งจะหยุดและเริ่มการรวบรวมโดยอัตโนมัติเมื่อสถานะ Lifecycle เปลี่ยนแปลง:

kotlin
viewModel.uiState
    .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
    .onEach { state -> updateUI(state) }
    .launchIn(lifecycleScope)

โอเปอเรเตอร์ flowWithLifecycle เป็นวิธีที่สั้นที่สุดในการสมัครรับ Flow อย่างปลอดภัยในเลเยอร์ UI

ตัวอย่างการใช้งาน lifecycleScope

มาดูสามสถานการณ์จริงของการใช้ lifecycleScope ในแอปพลิเคชัน Android ด้วย Kotlin

ตัวอย่างที่ 1: สมัครรับการอัปเดตตำแหน่งเฉพาะเมื่อหน้าจอมองเห็น

kotlin
class MapFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                locationProvider.observeLocation().collect { loc ->
                    updateMapMarker(loc)
                }
            }
        }
    }
}

coroutine เริ่มเมื่อ fragment ปรากฏ (STARTED) และถูกยกเลิกเมื่อออกจากหน้าจอ (STOPPED) หากผู้ใช้เปลี่ยนไปใช้แอปอื่น การอัปเดตตำแหน่งจะไม่กินแบตเตอรี่

ตัวอย่างที่ 2: เริ่มแอนิเมชันเมื่อ fragment เริ่ม

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.RESUMED) {
        animateFadeIn(titleView)
        delay(200)
        animateSlideUp(contentView)
    }
}

แอนิเมชันจะทำงานเมื่อ fragment อยู่ในเบื้องหน้าเท่านั้น (RESUMED) หากผู้ใช้ย่อแอประหว่างแอนิเมชัน coroutine จะถูกยกเลิก และเมื่อกลับมา แอนิเมชันจะเริ่มใหม่

ตัวอย่างที่ 3: การซิงค์ข้อมูลเป็นระยะบนหน้าจอที่มองเห็น

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        while (isActive) {
            syncData()
            delay(30_000L)
        }
    }
}

ข้อมูลจะถูกซิงค์ทุก 30 วินาที แต่เฉพาะเมื่อหน้าจอมองเห็น isActive ตรวจสอบว่า coroutine ถูกยกเลิกหรือไม่ ซึ่งเป็นวิธีที่ปลอดภัยในการออกจากลูปเมื่อออกจากหน้าจอ

lifecycleScope กับ viewModelScope: สถานการณ์การใช้งาน

ทั้งสอง scope เชื่อมโยงกับวงจรชีวิต แต่กับคนละด้าน การเข้าใจความแตกต่างเป็นสิ่งสำคัญสำหรับสถาปัตยกรรมแอปพลิเคชัน Android ที่ถูกต้อง

ความแตกต่างหลัก

viewModelScope เชื่อมโยงกับ ViewModel ซึ่งคงอยู่เมื่อหมุนหน้าจอ lifecycleScope เชื่อมโยงกับ LifecycleOwner (Activity/Fragment) ซึ่งถูกทำลายและสร้างใหม่เมื่อหมุน สิ่งนี้กำหนดสถานการณ์การใช้งาน

เมื่อใดควรใช้ lifecycleScope

  • สมัครรับเหตุการณ์ระบบ (ตำแหน่ง, เซ็นเซอร์, กล้อง)
  • แอนิเมชันและเอฟเฟกต์ UI ที่เชื่อมโยงกับหน้าจอเฉพาะ
  • การโหลดข้อมูลเป็นชิ้นตามการมองเห็นของหน้าจอ
  • การดำเนินการที่ควรหยุดเมื่อออกจากหน้าจอ

เมื่อใดควรใช้ viewModelScope

  • การโหลดข้อมูลจาก Repository
  • ตรรกะทางธุรกิจที่ควรคงอยู่เมื่อหมุน
  • การแคชและการประมวลผลข้อมูล
  • การดำเนินการใดๆ ที่ต้องการผลลัพธ์หลังการหมุน

การใช้ร่วมกัน

ในทางปฏิบัติ การรวมกันของทั้งสอง scope เป็นเรื่องปกติ: viewModelScope โหลดข้อมูลและจัดการสถานะ ในขณะที่ lifecycleScope สมัครรับ Flow จาก ViewModel โดยรับรู้วงจรชีวิต การแยกความรับผิดชอบนี้ถือเป็น แนวปฏิบัติที่ดีที่สุด ในการพัฒนา Android สมัยใหม่

ข้อผิดพลาดทั่วไปเมื่อทำงานกับ lifecycleScope

มาดูสี่ข้อผิดพลาดทั่วไปที่นักพัฒนาทำเมื่อใช้ lifecycleScope

ข้อผิดพลาด 1: ใช้ lifecycleScope แทน viewModelScope สำหรับการโหลดข้อมูล

หากคุณเริ่มการโหลดข้อมูลใน lifecycleScope.launch coroutine จะถูกยกเลิกเมื่อหมุนหน้าจอและข้อมูลจะต้องโหลดใหม่ ใช้ viewModelScope สำหรับการดำเนินการที่อายุยืน lifecycleScope มีไว้สำหรับงานที่เชื่อมโยงกับ UI เท่านั้น

ข้อผิดพลาด 2: รวบรวม Flow โดยไม่มี repeatOnLifecycle

การเรียก viewModel.someFlow.collect { ... } โดยตรงภายใน lifecycleScope.launch จะยังคงรวบรวมข้อมูลต่อไปแม้เมื่อหน้าจอไม่ปรากฏ สิ่งนี้อาจทำให้เกิดการอัปเดต UI ในพื้นหลังและค่าใช้จ่ายที่ไม่จำเป็น ใช้ repeatOnLifecycle หรือ flowWithLifecycle เสมอ

ข้อผิดพลาด 3: ลืมยกเลิกเมื่อออกจากหน้าจอ

แม้ว่า lifecycleScope จะถูกยกเลิกที่ DESTROYED แต่โค้ดหลังจากจุดระงับ (suspend) อาจไม่ทำงานเมื่อถูกยกเลิกกะทันหัน อย่าพึ่งพาการทำงานของโค้ดหลังจากการเรียก suspend เว้นแต่คุณจะใช้ NonCancellable

ข้อผิดพลาด 4: ใช้ launchWhenStarted ที่เลิกใช้แล้วแทน repeatOnLifecycle

launchWhenStarted และสิ่งที่คล้ายกันไม่ยกเลิก coroutine แค่หยุดชั่วคราว หากหน้าจอสลับระหว่างเบื้องหน้าและพื้นหลังหลายครั้ง coroutine จะสะสมการเรียกที่ถูกเลื่อน เปลี่ยนไปใช้ repeatOnLifecycle — นี่เป็นวิธีที่ถูกต้องเท่านั้นในการซิงค์กับ Lifecycle

คำถามที่พบบ่อย

ความแตกต่างระหว่าง lifecycleScope และ GlobalScope คืออะไร?

lifecycleScope จะถูกยกเลิกโดยอัตโนมัติเมื่อ LifecycleOwner ถูกทำลาย GlobalScope มีชีวิตอยู่ตลอดเวลาที่แอปพลิเคชันทำงาน coroutine ใน lifecycleScope ไม่สามารถอัปเดต UI หลังจากคอมโพเนนต์ถูกทำลาย ในขณะที่ GlobalScope สามารถทำได้ ซึ่งทำให้เกิดข้อขัดข้อง ใช้ lifecycleScope ในเลเยอร์ UI เสมอ

สามารถใช้ lifecycleScope ใน ViewModel ได้หรือไม่?

ไม่ ViewModel ไม่ใช่ LifecycleOwner ดังนั้น lifecycleScope จึงไม่พร้อมใช้งานในนั้น ViewModel ใช้ viewModelScope หากโค้ดต้องทำงานในทั้งสองบริบท ให้แยกตรรกะออกไปยัง use case หรือ repository ด้วยฟังก์ชัน suspend

จะเกิดอะไรขึ้นเมื่อเรียก repeatOnLifecycle หลายครั้ง?

การเรียก repeatOnLifecycle แต่ละครั้งจะสร้าง coroutine ใหม่ที่เรียกใช้บล็อกเมื่อถึงสถานะ Lifecycle ที่ระบุ หากเรียก repeatOnLifecycle สองครั้งสำหรับสถานะเดียวกัน ทั้งสองบล็อกจะทำงานอย่างอิสระ โดยทั่วไปการเรียกครั้งเดียวใน onViewCreated ก็เพียงพอ

สามารถตั้งค่า Dispatcher ที่กำหนดเองสำหรับ lifecycleScope ได้หรือไม่?

คุณไม่สามารถเปลี่ยนตัวจัดส่งของ lifecycleScope ได้โดยตรง — มันใช้ Dispatchers.Main.immediate ภายในบล็อก coroutine คุณสามารถสลับไปยังตัวจัดส่งอื่นผ่าน withContext สำหรับการทดสอบ ให้ใช้ TestDispatcher กับ LifecycleOwner

lifecycleScope ถูกยกเลิกใน onPause หรือ onDestroy?

lifecycleScope จะถูกยกเลิกเมื่อ LifecycleOwner เปลี่ยนไปเป็นสถานะ DESTROYED (หลัง onDestroy) การเรียก lifecycleScope.launch อย่างง่ายจะไม่ถูกยกเลิกใน onPause หรือ onStop หากต้องการหยุดชั่วคราวเมื่อไปที่พื้นหลัง ให้ใช้ repeatOnLifecycle(STARTED) หรือ repeatOnLifecycle(RESUMED)

สรุป

  • lifecycleScope — CoroutineScope ที่เชื่อมโยงกับ LifecycleOwner และถูกยกเลิกอัตโนมัติที่ DESTROYED ผ่าน LifecycleEventObserver
  • Dispatchers.Main.immediate — ตัวจัดส่งเริ่มต้น รับประกันการอัปเดต UI ที่ปลอดภัยโดยไม่ต้องสลับโดยไม่จำเป็น
  • repeatOnLifecycle — API ที่ทันสมัยสำหรับเริ่ม coroutine ที่สถานะ Lifecycle ที่ระบุพร้อมการยกเลิกและเริ่มใหม่โดยอัตโนมัติ
  • flowWithLifecycle — โอเปอเรเตอร์สำหรับรวบรวม Flow อย่างปลอดภัยจาก UI โดยรับรู้วงจรชีวิต
  • launchWhenStarted เลิกใช้แล้ว — แทนที่จะหยุดชั่วคราว ให้ใช้ repeatOnLifecycle ซึ่งยกเลิก coroutine แทนที่จะหยุด
  • lifecycleScope กับ viewModelScope — lifecycleScope สำหรับการดำเนินการ UI (แอนิเมชัน, ตำแหน่ง), viewModelScope สำหรับข้อมูลและตรรกะทางธุรกิจ
  • การหมุนหน้าจอ — lifecycleScope จะถูกยกเลิกเมื่อหมุน, viewModelScope คงอยู่; เลือก scope ตามงาน

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม