Skip to content

Commit ec86230

Browse files
authored
fix(Android, Stack v5): update stack model after native pop (#3599)
## Description Currently when doing native pop, the `stackModel` stored in `StackContainer` is never updated, therefore leading to an incorrect state held (natively dismissed fragments are never removed from the state). This PR changes that. ## Changes Currently I remove them from the state in `onFragmentDestroyView`, and it seems to work, however I'm not sure, this is the perfect place timing-wise. This callback is called only after fragment's view is destroyed, which might be pretty late in component lifecycle, and we might execute container operations still taking into consideration possibly removed screens. We need to look into that later. ## Before & after - visual documentation N/A ## Test plan Only sensible way to test this is to add logging in `StackContainer` and dismiss few screens natively, and see that the state is updated (with this fix). ## Checklist - [x] Ensured that CI passes
1 parent 523a736 commit ec86230

1 file changed

Lines changed: 17 additions & 4 deletions

File tree

android/src/main/java/com/swmansion/rnscreens/gamma/stack/host/StackContainer.kt

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.swmansion.rnscreens.gamma.stack.host
22

33
import android.annotation.SuppressLint
44
import android.content.Context
5+
import android.util.Log
56
import androidx.coordinatorlayout.widget.CoordinatorLayout
67
import androidx.fragment.app.FragmentManager
78
import com.swmansion.rnscreens.gamma.helpers.FragmentManagerHelper
@@ -19,7 +20,14 @@ internal class StackContainer(
1920
) : CoordinatorLayout(context) {
2021
private var fragmentManager: FragmentManager? = null
2122

22-
private val stackScreenFragments: MutableList<StackScreenFragment> = arrayListOf()
23+
/**
24+
* Describes most up-to-date view of the stack. It might be different from
25+
* state kept by FragmentManager as this data structure is updated immediately,
26+
* while operations on fragment manager are scheduled.
27+
*
28+
* FIXME: In case of native-pop, this might be out of date!
29+
*/
30+
private val stackModel: MutableList<StackScreenFragment> = arrayListOf()
2331

2432
private val pendingPopOperations: MutableList<PopOperation> = arrayListOf()
2533
private val pendingPushOperations: MutableList<PushOperation> = arrayListOf()
@@ -67,6 +75,8 @@ internal class StackContainer(
6775
}
6876

6977
private fun performOperations(fragmentManager: FragmentManager) {
78+
// TODO: Handle case when we have pop & push of the same screen in single batch.
79+
7080
pendingPopOperations.forEach { performPopOperation(fragmentManager, it) }
7181
pendingPushOperations.forEach { performPushOperation(fragmentManager, it) }
7282

@@ -81,7 +91,7 @@ internal class StackContainer(
8191
val transaction = fragmentManager.createTransactionWithReordering()
8292

8393
val associatedFragment = StackScreenFragment(WeakReference(this), operation.screen)
84-
stackScreenFragments.add(associatedFragment)
94+
stackModel.add(associatedFragment)
8595

8696
transaction.add(this.id, associatedFragment)
8797

@@ -97,7 +107,7 @@ internal class StackContainer(
97107
fragmentManager: FragmentManager,
98108
operation: PopOperation,
99109
) {
100-
val associatedFragment = stackScreenFragments.find { it.stackScreen === operation.screen }
110+
val associatedFragment = stackModel.find { it.stackScreen === operation.screen }
101111
require(associatedFragment != null) {
102112
"[RNScreens] Unable to find a fragment to pop."
103113
}
@@ -115,10 +125,13 @@ internal class StackContainer(
115125
transaction.commitNowAllowingStateLoss()
116126
}
117127

118-
stackScreenFragments.remove(associatedFragment)
128+
stackModel.remove(associatedFragment)
119129
}
120130

121131
internal fun onFragmentDestroyView(fragment: StackScreenFragment) {
132+
if (stackModel.remove(fragment) && !fragment.stackScreen.isNativelyDismissed) {
133+
Log.e(TAG, "[RNScreens] StackContainer natively popped a screen that was not in model!")
134+
}
122135
delegate.get()?.onScreenDismiss(fragment.stackScreen)
123136
}
124137

0 commit comments

Comments
 (0)