diff --git a/formula-android/src/main/java/com/instacart/formula/android/FragmentFlowStore.kt b/formula-android/src/main/java/com/instacart/formula/android/FragmentFlowStore.kt index d0e408bd..65fa2053 100644 --- a/formula-android/src/main/java/com/instacart/formula/android/FragmentFlowStore.kt +++ b/formula-android/src/main/java/com/instacart/formula/android/FragmentFlowStore.kt @@ -5,6 +5,7 @@ import com.instacart.formula.Formula import com.instacart.formula.Snapshot import com.instacart.formula.android.internal.Binding import com.instacart.formula.android.events.FragmentLifecycleEvent +import com.instacart.formula.android.internal.FeatureObservableAction import com.instacart.formula.rxjava3.RxAction import com.instacart.formula.rxjava3.toObservable import com.jakewharton.rxrelay3.PublishRelay @@ -122,14 +123,18 @@ class FragmentFlowStore @PublishedApi internal constructor( val fragmentId = entry.key val feature = (entry.value as? FeatureEvent.Init)?.feature if (feature != null) { - RxAction.fromObservable(feature) { - feature.state.onErrorResumeNext { - input.onScreenError(fragmentId.key, it) - Observable.empty() + val action = FeatureObservableAction( + fragmentEnvironment = input, + fragmentId = fragmentId, + feature = feature, + ) + action.onEvent { + if (state.activeIds.contains(fragmentId)) { + val keyState = FragmentState(fragmentId.key, it) + transition(state.copy(states = state.states.plus(fragmentId to keyState))) + } else { + none() } - }.onEvent { - val keyState = FragmentState(fragmentId.key, it) - transition(state.copy(states = state.states.plus(fragmentId to keyState))) } } } diff --git a/formula-android/src/main/java/com/instacart/formula/android/internal/ActivityManager.kt b/formula-android/src/main/java/com/instacart/formula/android/internal/ActivityManager.kt index 1dff4725..9089aeb2 100644 --- a/formula-android/src/main/java/com/instacart/formula/android/internal/ActivityManager.kt +++ b/formula-android/src/main/java/com/instacart/formula/android/internal/ActivityManager.kt @@ -6,7 +6,6 @@ import com.instacart.formula.android.events.ActivityResult import com.instacart.formula.android.FragmentEnvironment import com.instacart.formula.android.ActivityStore import com.instacart.formula.android.FormulaFragment -import com.instacart.formula.android.FragmentFlowState import com.instacart.formula.android.ViewFactory import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable @@ -20,12 +19,6 @@ internal class ActivityManager( private val store: ActivityStore ) { - private val fragmentState = store - .contracts - .state(environment) - .doOnNext(delegate.fragmentFlowStateRelay::accept) - .replay(1) - internal val stateSubscription: Disposable private var uiSubscription: Disposable? = null private var fragmentRenderView: FragmentFlowRenderView? = null @@ -33,11 +26,11 @@ internal class ActivityManager( init { stateSubscription = if (store.streams != null) { val disposables = CompositeDisposable() - disposables.add(fragmentState.connect()) + disposables.add(subscribeToFragmentStateChanges()) disposables.add(store.streams.invoke(StreamConfiguratorIml(delegate))) disposables } else { - fragmentState.connect() + subscribeToFragmentStateChanges() } } @@ -63,12 +56,10 @@ internal class ActivityManager( delegate.onLifecycleStateChanged(Lifecycle.State.CREATED) val renderView = fragmentRenderView ?: throw callOnPreCreateException(activity) - val updateScheduler = AndroidUpdateScheduler { + uiSubscription = delegate.fragmentFlowState().subscribe { renderView.render(it) store.onRenderFragmentState?.invoke(activity, it) } - - uiSubscription = fragmentState.subscribe(updateScheduler::emitUpdate) } fun onActivityStarted(activity: Activity) { @@ -115,6 +106,13 @@ internal class ActivityManager( return fragmentRenderView?.viewFactory(fragment) } + private fun subscribeToFragmentStateChanges(): Disposable { + return store + .contracts + .state(environment) + .subscribe(delegate.fragmentFlowStateRelay::accept) + } + private fun callOnPreCreateException(activity: FragmentActivity): IllegalStateException { return IllegalStateException("please call onPreCreate before calling Activity.super.onCreate(): ${activity::class.java.simpleName}") } diff --git a/formula-android/src/main/java/com/instacart/formula/android/internal/FeatureBinding.kt b/formula-android/src/main/java/com/instacart/formula/android/internal/FeatureBinding.kt index 6ef7bf65..4c4db867 100644 --- a/formula-android/src/main/java/com/instacart/formula/android/internal/FeatureBinding.kt +++ b/formula-android/src/main/java/com/instacart/formula/android/internal/FeatureBinding.kt @@ -32,7 +32,6 @@ internal class FeatureBinding, +) : Action { + + override fun key(): Any = fragmentId + + override fun start(send: (Any) -> Unit): Cancelable { + val observable = feature.state.onErrorResumeNext { + fragmentEnvironment.onScreenError(fragmentId.key, it) + Observable.empty() + } + + // We ensure all feature state updates come on the main thread. + val androidUpdateScheduler = AndroidUpdateScheduler(send) + val disposable = observable.subscribe(androidUpdateScheduler::emitUpdate) + return Cancelable(disposable::dispose) + } +} \ No newline at end of file diff --git a/formula-android/src/main/java/com/instacart/formula/android/internal/FragmentFlowRenderView.kt b/formula-android/src/main/java/com/instacart/formula/android/internal/FragmentFlowRenderView.kt index bc5aefb7..2b1d51b6 100644 --- a/formula-android/src/main/java/com/instacart/formula/android/internal/FragmentFlowRenderView.kt +++ b/formula-android/src/main/java/com/instacart/formula/android/internal/FragmentFlowRenderView.kt @@ -42,7 +42,6 @@ internal class FragmentFlowRenderView( private val featureProvider = object : FeatureProvider { override fun getFeature(id: FragmentId): FeatureEvent? { - // TODO: should we initialize feature if it's missing return fragmentState?.features?.get(id) } }