diff --git a/android/src/main/java/com/reactnativepagerview/ComposePagerView.kt b/android/src/main/java/com/reactnativepagerview/ComposePagerView.kt index 814b7df3..0426f522 100644 --- a/android/src/main/java/com/reactnativepagerview/ComposePagerView.kt +++ b/android/src/main/java/com/reactnativepagerview/ComposePagerView.kt @@ -33,6 +33,10 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.setViewTreeLifecycleOwner +import androidx.savedstate.SavedStateRegistry +import androidx.savedstate.SavedStateRegistryController +import androidx.savedstate.SavedStateRegistryOwner +import androidx.savedstate.setViewTreeSavedStateRegistryOwner import com.facebook.react.bridge.ReactContext import com.facebook.react.uimanager.UIManagerHelper import com.facebook.react.uimanager.events.NativeGestureUtil @@ -99,6 +103,13 @@ class ComposePagerView(context: Context) : FrameLayout(context) { // resolves it instead of walking up to the ambient (and repeatedly // destroyed) Fragment view-tree Lifecycle - see the field comment above. setViewTreeLifecycleOwner(composeLifecycleOwner) + // Same for saved state. Compose would otherwise store the pager's + // rememberSaveable state (current page, page view state) in the host + // Fragment's SavedStateRegistry under a key derived from this view's + // id. It has none, so every pager shares one key and a remounted pager + // restores the previous pager's page instead of using initialPage. + // React owns the pager state, so the owner's registry is never saved. + setViewTreeSavedStateRegistryOwner(composeLifecycleOwner) setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnLifecycleDestroyed(composeLifecycleOwner) ) @@ -687,18 +698,29 @@ class ComposePagerView(context: Context) : FrameLayout(context) { // A stable Lifecycle that follows the currently attached host through // CREATED/STARTED/RESUMED, but only moves to DESTROYED when destroy() is // called explicitly. This lets it survive react-native-screens replacing the -// ambient Fragment view-tree owner (see the field comment above). -internal class ComposeViewLifecycleOwner : LifecycleOwner, LifecycleEventObserver { - private val registry = LifecycleRegistry(this).apply { - currentState = Lifecycle.State.CREATED - } +// ambient Fragment view-tree owner (see the field comment above). It also +// provides an empty SavedStateRegistry that is never saved, so nothing in the +// composition is persisted or restored. +internal class ComposeViewLifecycleOwner : + LifecycleOwner, SavedStateRegistryOwner, LifecycleEventObserver { + private val registry = LifecycleRegistry(this) + private val savedStateController = SavedStateRegistryController.create(this) private var hostLifecycle: Lifecycle? = null private var isAttached = false private var isDestroyed = false + init { + // Must run while the Lifecycle is still INITIALIZED. + savedStateController.performRestore(null) + registry.currentState = Lifecycle.State.CREATED + } + override val lifecycle: Lifecycle get() = registry + override val savedStateRegistry: SavedStateRegistry + get() = savedStateController.savedStateRegistry + fun attach(lifecycle: Lifecycle?) { if (isDestroyed) { return