https://kotlinlang.org logo
#coroutines
Title
# coroutines
f

Florian

12/17/2020, 7:58 AM
Is there something like
flatMapLatest
that I can trigger explicitly and only once? I want to switch a Flow to another Flow if a certain condition is met
b

bezrukov

12/17/2020, 8:49 AM
will it work for you?
firstFlow.filter { condition }.take(1).flatMapLatest { secondFlow }
☝️ 1
f

Florian

12/17/2020, 9:09 AM
no I don't think so
my Flow is a property while the condition happens inside the
init
block
g

Giorgos Neokleous

12/17/2020, 9:15 AM
Can you not wrap your emissions into an Either? You can do a homemade either or pull down arrow and use it. You can wrap your emissions into Either left or right based on your condition and unwrapped it on the collection of the flow
w

wasyl

12/17/2020, 10:10 AM
@Florian Do you mean something like this?
Copy code
@Test
fun `switching flows`() {
    val condition = MutableStateFlow(false)
    val firstFlow = flow {
        var i = 0
        while (true) {
            emit("original: ${i++}")
            delay(10)
        }
    }
    val secondFlow = flow {
        var i = 0
        while (true) {
            emit("modified: ${i++}")
            delay(10)
        }
    }

    runBlocking {
        val job = launch {
            condition
                .flatMapLatest { switched -> if (switched) secondFlow else firstFlow }
                .collect { println(it) }
        }

        delay(100)
        condition.value = true
        delay(200)
        job.cancel()
    }
}
f

Florian

12/17/2020, 5:27 PM
I need the Flow as a property
this s my current code:
Copy code
private val chatMessagesHistoryFlow = chat.asFlow()
        .flatMapLatest { chat ->
            chat?.let {
                chatRepository.getChatMessagesHistory(it).cachedIn(viewModelScope)
            } ?: emptyFlow()
        }.catch { t ->
            showErrorMessage(t.localizedMessage ?: "Message couldn't be loaded")
            emit(PagingData.empty())
        }
but I want to do this only in the
init
block
maybe I need to collect inside the
init
block?
Copy code
viewModelScope.launch {
    searchingForExistingDirectChat?.join()
    chat.value?.let { chat ->
        chatRepository.getChatMessagesHistory(chat).cachedIn(viewModelScope)
            .catch { t ->
                showErrorMessage(t.localizedMessage ?: "Messages couldn't be loaded")
                emit(PagingData.empty())
            }
            .collect { 
                   chatMessagesHistoryChannel.send(it)
            }
    }
}
Does this make sense?
is there something else than a channel where I could put the collected values into?
5 Views