|
| 1 | +package com.squareup.workflow1.ui.compose |
| 2 | + |
| 3 | +import androidx.compose.runtime.RememberObserver |
| 4 | +import androidx.lifecycle.Lifecycle |
| 5 | +import androidx.lifecycle.LifecycleEventObserver |
| 6 | +import androidx.lifecycle.LifecycleOwner |
| 7 | +import androidx.lifecycle.LifecycleRegistry |
| 8 | + |
| 9 | +/** |
| 10 | + * A custom [LifecycleOwner] that synchronizes its lifecycle with a parent [Lifecycle] and |
| 11 | + * integrates with Jetpack Compose's lifecycle through [RememberObserver]. |
| 12 | + * |
| 13 | + * **Purpose:** |
| 14 | + * |
| 15 | + * - Ensures that any lifecycle-aware components within a composable function have a lifecycle that |
| 16 | + * accurately reflects both the parent lifecycle and the composable's own lifecycle. |
| 17 | + * - Manages lifecycle transitions and observer registration/removal to prevent memory leaks and |
| 18 | + * ensure proper cleanup when the composable leaves the composition. |
| 19 | + * |
| 20 | + * **Key Features:** |
| 21 | + * |
| 22 | + * - **Lifecycle Synchronization:** Mirrors lifecycle events from the provided `parentLifecycle` to |
| 23 | + * its own [LifecycleRegistry], ensuring consistent state transitions. |
| 24 | + * - **Compose Integration:** Implements [RememberObserver] to align with the composable's lifecycle |
| 25 | + * in the Compose memory model. |
| 26 | + * - **Automatic Observer Management:** Adds and removes a [LifecycleEventObserver] to the parent |
| 27 | + * lifecycle, preventing leaks and ensuring proper disposal. |
| 28 | + * - **State Transition Safety:** Carefully manages lifecycle state changes to avoid illegal |
| 29 | + * transitions, especially during destruction. |
| 30 | + * |
| 31 | + * **Usage Notes:** |
| 32 | + * |
| 33 | + * - Should be used in conjunction with `remember` and provided the `parentLifecycle` as a key to |
| 34 | + * ensure it updates correctly when the parent lifecycle changes. |
| 35 | + * - By integrating with Compose's lifecycle, it ensures that resources are properly released when |
| 36 | + * the composable leaves the composition. |
| 37 | + * |
| 38 | + * @param parentLifecycle The parent [Lifecycle] with which this lifecycle owner should synchronize. |
| 39 | + */ |
| 40 | +internal class ComposeLifecycleOwner( |
| 41 | + private val parentLifecycle: Lifecycle |
| 42 | +) : LifecycleOwner, RememberObserver { |
| 43 | + |
| 44 | + private val registry = LifecycleRegistry(this) |
| 45 | + override val lifecycle: Lifecycle |
| 46 | + get() = registry |
| 47 | + |
| 48 | + private val parentObserver = LifecycleEventObserver { _, event -> |
| 49 | + // Any time the parent lifecycle changes state, perform the same change on our lifecycle. |
| 50 | + registry.handleLifecycleEvent(event) |
| 51 | + } |
| 52 | + |
| 53 | + init { |
| 54 | + // We do this right away to ensure that the parent lifecycle is observed as soon as possible |
| 55 | + // to prevent any inconsistencies. |
| 56 | + parentLifecycle.addObserver(parentObserver) |
| 57 | + } |
| 58 | + |
| 59 | + override fun onRemembered() { |
| 60 | + |
| 61 | + } |
| 62 | + |
| 63 | + override fun onAbandoned() { |
| 64 | + onForgotten() |
| 65 | + } |
| 66 | + |
| 67 | + override fun onForgotten() { |
| 68 | + parentLifecycle.removeObserver(parentObserver) |
| 69 | + |
| 70 | + // If we're leaving the composition, ensure the lifecycle is cleaned up |
| 71 | + if (registry.currentState != Lifecycle.State.INITIALIZED) { |
| 72 | + registry.currentState = Lifecycle.State.DESTROYED |
| 73 | + } |
| 74 | + } |
| 75 | +} |
0 commit comments