วงจรของ Jetpack Compose   ส่วนหนึ่งของ Android Jetpack

คอมโพเนนต์ที่รับรู้ถึงวงจรจะดำเนินการเพื่อตอบสนองต่อการเปลี่ยนแปลง สถานะวงจรของกิจกรรมโฮสต์ อาร์ติแฟกต์ androidx.lifecycle.compose มี API เฉพาะที่จะล้างข้อมูลทรัพยากรโดยอัตโนมัติเมื่อทรัพยากร ออกจากหน้าจอหรือเมื่อแอปพลิเคชันเข้าสู่เบื้องหลัง

API หลักๆ มีดังนี้

  • โฟลว์สำหรับ Lifecycle.State ปัจจุบัน
  • LifecycleEffects ซึ่งช่วยให้คุณเรียกใช้บล็อกตาม Lifecycle.Event ที่เฉพาะเจาะจงได้

การผสานรวมเหล่านี้มีฮุกที่สะดวกในการจัดการวงจรภายในลำดับชั้น Compose เอกสารนี้จะอธิบายวิธีใช้ในแอป

รวบรวมสถานะวงจรของลูกค้าด้วยโฟลว์

Lifecycle แสดงพร็อพเพอร์ตี้ currentStateFlow ที่ให้Lifecycle.Stateปัจจุบันเป็น StateFlow ของ Kotlin คุณสามารถรวบรวม Flow นี้เป็นState ซึ่งจะช่วยให้แอปอ่านการเปลี่ยนแปลงในวงจรขององค์ประกอบระหว่างการเขียนได้

val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow

val currentLifecycleState by stateFlow.collectAsState()

ตัวอย่างก่อนหน้าสามารถเข้าถึงได้โดยใช้โมดูล lifecycle-common เมธอด currentStateAsState()พร้อมใช้งานในโมดูล lifecycle-runtime-compose ซึ่งช่วยให้คุณอ่านสถานะ Lifecycle ปัจจุบันได้อย่างสะดวกด้วยโค้ดเพียงบรรทัดเดียว ตัวอย่างต่อไปนี้แสดงให้เห็นถึงเรื่องนี้

val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()

เรียกใช้โค้ดในเหตุการณ์วงจร

แทนที่จะสร้างคลาสแยกต่างหากที่ใช้ DefaultLifecycleObserver และเพิ่มลงในวงจรด้วยตนเอง คุณสามารถประกาศตรรกะวงจรแบบอินไลน์โดยใช้เอฟเฟกต์ที่เฉพาะเจาะจงได้ LifecycleEffects ช่วยให้คุณเรียกใช้บล็อกเมื่อLifecycle.Event ที่เฉพาะเจาะจงเกิดขึ้นภายในคอมโพสิชันโดยตรง

LifecycleEventEffect

ใช้ LifecycleEventEffect เพื่อเรียกใช้บล็อกโค้ด เมื่อเกิดเหตุการณ์ที่เฉพาะเจาะจง เหมาะที่สุดสำหรับเหตุการณ์แบบครั้งเดียว เช่น การบันทึกหรือการวิเคราะห์ ซึ่งไม่จำเป็นต้องมีผลลัพธ์ที่สำเร็จหรือผลลัพธ์ในทันที

@Composable
fun AnalyticsTracker(screenName: String) {
    // Log an event when the app receives ON_RESUME (e.g. comes to foreground)
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        Analytics.logView(screenName)
    }
}

LifecycleStartEffect

สำหรับการดำเนินการเริ่ม/หยุดที่จับคู่กันซึ่งต้องเรียกใช้ขณะที่แอปเริ่มต้น (มองเห็นได้) และล้างข้อมูลเมื่อแอปหยุดทำงาน (ในเบื้องหลัง) ให้ใช้ LifecycleStartEffect

LifecycleStartEffect ยอมรับคีย์เช่นเดียวกับเอฟเฟกต์ Compose อื่นๆ (เช่น LaunchedEffect) เมื่อคีย์มีการเปลี่ยนแปลง ระบบจะทริกเกอร์ให้บล็อกทำงานอีกครั้ง

เมื่อเกิดเหตุการณ์ Lifecycle.Event.ON_STOP หรือเอฟเฟกต์ออกจาก คอมโพสิต ระบบจะเรียกใช้บล็อก onStopOrDispose เพื่อล้างข้อมูลใดๆ ที่ เป็นส่วนหนึ่งของบล็อกเริ่มต้น

@Composable
fun LocationMonitor(locationManager: LocationManager) {
    // Starts monitoring when ON_START is dispatched
    // Stops monitoring when ON_STOP is dispatched
    //   (or the composable leaves the screen)
    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { location ->
            /* update UI */
        }
        locationManager.requestLocationUpdates(listener)
        // The cleanup block automatically runs on ON_STOP or on disposal
        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
}

ดูข้อมูลเกี่ยวกับผลข้างเคียงประเภทอื่นๆ ได้ที่ผลข้างเคียงใน Compose

LifecycleResumeEffect

LifecycleResumeEffect ทำงานในลักษณะเดียวกับ LifecycleStartEffect แต่จะเชื่อมโยงกับเหตุการณ์ Lifecycle.Event.ON_RESUME แทน นอกจากนี้ ยังมีonPauseOrDisposeบล็อกที่ทำการล้างข้อมูลเมื่อON_PAUSE ถูกส่ง หรือ Composable ออกจากหน้าจอ

API นี้มีประโยชน์สำหรับทรัพยากรที่ต้องใช้งานเมื่อผู้ใช้ โต้ตอบกับแอปเท่านั้น เช่น กล้องหรือภาพเคลื่อนไหว

@Composable
fun CameraPreview(cameraController: CameraController) {
    LifecycleResumeEffect(cameraController) {
        cameraController.startPreview()

        onPauseOrDispose {
            cameraController.stopPreview()
        }
    }
}

เข้าถึง LifecycleOwner

ใน Compose LifecycleOwner จะ พร้อมใช้งานโดยปริยายผ่าน CompositionLocal ที่ชื่อ LocalLifecycleOwner โดย ค่าเริ่มต้น โฮสต์รูทของลำดับชั้นการเรียบเรียงจะระบุเจ้าของนี้

val lifecycleOwner = LocalLifecycleOwner.current

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

สร้าง LifecycleOwner ที่กำหนดเอง

rememberLifecycleOwner() API ช่วยให้คุณสร้างและจดจำLifecycleOwnerที่กำหนดเองได้ ซึ่งมีประโยชน์อย่างยิ่งสำหรับคอมโพเนนต์อย่างเช่น HorizontalPager ซึ่งคุณต้องการให้เฉพาะหน้าที่มองเห็นและโหลดเสร็จแล้วเป็น RESUMED ขณะตั้งค่า maxState เป็น STARTED สำหรับหน้าที่อยู่ติดกันซึ่งอยู่นอกหน้าจอ

val pagerState = rememberPagerState(pageCount = { 10 })

HorizontalPager(state = pagerState) { pageNum ->
    val pageLifecycleOwner = rememberLifecycleOwner(
        maxState = if (pagerState.settledPage == pageNum) {
            Lifecycle.State.RESUMED
        } else {
            Lifecycle.State.STARTED
        }
    )

    CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
        // Your pages here. Their lifecycle-aware components respect the
        // custom maxState defined above.
    }
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับ CompositionLocal ได้ที่ข้อมูลที่กำหนดขอบเขตในเครื่องด้วย CompositionLocal

แนวทางปฏิบัติแนะนำสำหรับคอมโพเนนต์ที่รับรู้ถึงวงจร

  • ทำให้ตัวควบคุม UI มีขนาดเล็กที่สุด โดยไม่ควรพยายามรับข้อมูลของตนเอง แต่ให้ใช้ ViewModel เพื่อดำเนินการดังกล่าว และสังเกตออบเจ็กต์ StateFlow เพื่อแสดงการเปลี่ยนแปลงกลับไปยัง UI
  • พยายามเขียน UI ที่อิงตามข้อมูลซึ่งความรับผิดชอบของตัวควบคุม UI คือการ อัปเดต UI เมื่อข้อมูลเปลี่ยนแปลง หรือแจ้งการดำเนินการของผู้ใช้กลับไปยัง ViewModel
  • วางตรรกะข้อมูลไว้ในคลาส ViewModel ViewModel ควรทำหน้าที่เป็นตัวเชื่อมต่อระหว่างตัวควบคุม UI กับส่วนอื่นๆ ของแอป แต่โปรดระวังเนื่องจาก ViewModel ไม่ได้มีหน้าที่ดึงข้อมูล (เช่น จากเครือข่าย) แต่ ViewModel ควรเรียกใช้คอมโพเนนต์ที่เหมาะสมเพื่อดึงข้อมูล แล้วส่งผลลัพธ์กลับไปยังตัวควบคุม UI
  • ใช้ Kotlin Coroutines เพื่อจัดการ งานที่ใช้เวลานานและดำเนินการอื่นๆ ที่ทำงานแบบไม่พร้อมกันได้
  • เก็บตรรกะการเริ่ม/หยุดไว้ใน Composable ที่ต้องการจริงๆ วิธีนี้จะช่วยให้ระบบนำตรรกะออกโดยอัตโนมัติหากมีการนำองค์ประกอบ UI ที่เฉพาะเจาะจงนั้นออกจากหน้าจอ (เช่น ภายในกราฟการนำทางหรือเมื่อการมองเห็นเป็นแบบมีเงื่อนไข)
  • ใช้ collectAsStateWithLifecycle สำหรับข้อมูล อย่าเริ่มหรือหยุดFlowการรวบรวมด้วยตนเองตามเหตุการณ์ในวงจร แต่ให้ใช้ collectAsStateWithLifecycle เพื่อแปลงสตรีมเป็นสถานะ UI อย่างมีประสิทธิภาพแทน ซึ่งจะช่วยประหยัดแบตเตอรี่และทรัพยากรเนื่องจากระบบจะหยุดFlowชั่วคราวเมื่อแอปทำงานในเบื้องหลัง

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Flow ได้ที่ประเภทสถานะอื่นๆ ที่รองรับ

กรณีการใช้งานสำหรับคอมโพเนนต์ที่รับรู้ถึงวงจร

คอมโพเนนต์ที่รับรู้ถึงวงจรช่วยให้คุณจัดการวงจรได้ง่ายขึ้นมาก ในหลายๆ กรณี ตัวอย่างเช่น

  • การสลับระหว่างการอัปเดตตำแหน่งแบบหยาบและแบบละเอียด ใช้ LifecycleStartEffect เพื่อเปิดใช้การอัปเดตตำแหน่งแบบละเอียดขณะที่ แอปปรากฏอยู่ (ON_START) และล้างข้อมูล Listener โดยอัตโนมัติหรือ เปลี่ยนไปใช้การอัปเดตแบบหยาบเมื่อแอปทำงานในเบื้องหลัง (ON_STOP)
  • หยุดและเริ่มการบัฟเฟอร์วิดีโอ ใช้ LifecycleResumeEffect เพื่อเลื่อน การเล่นวิดีโอจริงจนกว่าแอปจะอยู่เบื้องหน้าอย่างเต็มรูปแบบและ โต้ตอบได้ (ON_RESUME) และเพื่อให้แน่ใจว่าการเล่นจะหยุดชั่วคราวและ ปล่อยทรัพยากรเมื่อแอปทำงานในเบื้องหลัง (ON_PAUSE)
  • การเริ่มและหยุดการสตรีมเครือข่าย ใช้ collectAsStateWithLifecycle เพื่อสังเกตสตรีมข้อมูลอย่างต่อเนื่อง (เช่น Kotlin Flow จากซ็อกเก็ตเครือข่าย ) ซึ่งจะช่วยให้คุณอัปเดตได้แบบเรียลไทม์ขณะที่แอปทำงานในเบื้องหน้า และยกเลิกการรวบรวมโดยอัตโนมัติเมื่อแอปทำงานในเบื้องหลัง
  • หยุดชั่วคราวและกลับมาทำงานหนักอีกครั้ง ใช้ LifecycleResumeEffect เพื่อจัดการ การหยุดการอัปเดตภาพที่ใช้ทรัพยากรมากชั่วคราวเมื่อแอปอยู่ในเบื้องหลัง และดำเนินการต่อ หลังจากที่แอปอยู่ในเบื้องหน้า

การจัดการเหตุการณ์ ON_STOP อย่างปลอดภัย

Compose ออกแบบมาเพื่อจัดการเหตุการณ์ ON_STOP อย่างปลอดภัย

  • สถานะปลอดภัย: คุณอัปเดต MutableState (เช่น ด้วย uiState.value = ...) ได้ทุกเมื่อ แม้ว่าแอปจะทำงานในเบื้องหลังก็ตาม Compose จะรอจนกว่าแอปจะแสดงให้เห็นเพื่อแสดงผลการเปลี่ยนแปลง
  • การล้างข้อมูลอัตโนมัติ: ด้วยเอฟเฟกต์อย่าง LifecycleStartEffect บล็อกการล้างข้อมูล (onStopOrDispose) จะทำงานเมื่อวงจรชีวิตเปลี่ยนไปเป็น STOPPED ซึ่งจะช่วยป้องกันไม่ให้คุณถือครองทรัพยากรที่มีน้ำหนักมาก (เช่น กล้องหรือ ตำแหน่ง) ขณะที่แอปทำงานในเบื้องหลัง

ดูข้อมูลเพิ่มเติมเกี่ยวกับ MutableState ได้ที่สถานะและ Jetpack Compose

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับการจัดการวงจรด้วยคอมโพเนนต์ที่รับรู้ถึงวงจรได้จากแหล่งข้อมูลเพิ่มเติมต่อไปนี้

ดูเนื้อหา