Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions android/src/main/java/com/reactnativepagerview/ComposePagerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
)
Expand Down Expand Up @@ -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
Expand Down
Loading