Hey guys, what's the best way to listen to Flow in...
# orbit-mvi
b
Hey guys, what's the best way to listen to Flow inputs from a ContainerHost? I'm doing this
Copy code
public class MyContainerHost(
    scope: CoroutineScope,
    dataFlow: Flow<String>
) : ContainerHost<MyContainerHost.State, Unit> {

    public data class State(val value: String)

    override val container: Container<State, Unit> = scope.container(State("")) {
        scope.launch {
            dataFlow.collectLatest { flowValue ->
                intent {                
                    // This is never reached during tests
                    reduce {
                        state.copy(value = flowValue)
                    }
                }
            }
        }
    }
}
And I'm testing it like so
Copy code
@Test
fun the_test() {
    runTest {
        val ch = MyContainerHost(scope = this, dataFlow = flowOf("Some value"))
        val testCH = ch.test(isolateFlow = false)
        testCH.runOnCreate()
        delay(1000)

        val lastState = testCH.stateObserver.values.last()
        assertEquals("Some value", lastState.value)
    }
}
But the test fails because the
intent{}
block is never called.
collectLatest
calls
intent
but its content, the reduce function, is never called. This is only an issue during testing Any idea?
v
I think that explicit launch is messing things up for you.
Copy code
public class MyContainerHost(
    scope: CoroutineScope,
    dataFlow: Flow<String>
) : ContainerHost<MyContainerHost.State, Unit> {

    public data class State(val value: String)

    override val container: Container<State, Unit> = scope.container(State("")) {
        intent { // This should work
            dataFlow.collectLatest { flowValue ->
                reduce {
                    state.copy(value = flowValue)
                }
            }
        }
    }
}
b
Thanks! It works, but that means having a long running intent though, is it not a bad thing?
👍 1
v
Yeah, I think we're good. Plus this is also the official recommendation That said, we might need to think about two things: 1. Do we need a repeatOnSubscription block inside our intent (The example in above link uses
runOnSubscription
not sure if this is a typo 😅) 2. As per the docs "Cancellation happens automatically when the Orbit coroutine scope cancels." ...and we have a custom scope to deal with.
💯 1