StateFlow .combine usage with .asLiveData
See original GitHub issueI’m using StateFlow
under the hood, but still exposing LiveData
in my API. I’m currently experiencing some unexpected behavior with regard to calling combine
to join two instances of MutableStateFlow
, and subsequently using the combined value as LiveData
.
private val _read = MutableStateFlow<ChannelUserRead?>(null)
private val _messages = MutableStateFlow<Map<String, Message>>(emptyMap())
...
private val _unreadCount: StateFlow<Int?> =
_read.combine(_messages) { channelUserRead: ChannelUserRead?, messagesMap: Map<String, Message> ->
computeUnreadCount(domainImpl.currentUser, channelUserRead, messagesMap.values.toList())
}.stateIn(domainImpl.scope, SharingStarted.Eagerly, 0)
override val unreadCount: LiveData<Int?> = _unreadCount.asLiveData()
I would expect this to run the combine transformation any time _read
or _messages
value changes, and also notify any observers of the unreadCount
. This seems to work in the acutal app, but previously passing tests now fail when trying to validate unreadCount.value
. It seems that, when under test, the combine transformation is called once on instantiation, and not when _messages.value
is updated, and so
channelController.unreadCount.getOrAwaitValue().let { unreadCount ->
Truth.assertThat(unreadCount).isEqualTo(1)
}
always fails with actual being 0.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:8 (4 by maintainers)
Top Results From Across the Web
How to combine livedata and kotlin flow - Stack Overflow
You can combine both streams of data into one stream and use their results. For example we can convert LiveData to Flow ,...
Read more >Using StateFlow over LiveData for end-to-end operations
I'll demonstrate their use in a small sample app that leverages StateFlow for two use cases. First, we'll see how it provides the...
Read more >StateFlow and SharedFlow - Android Developers
StateFlow and SharedFlow are Flow APIs that enable flows to optimally emit state updates and emit values to multiple consumers.
Read more >Kotlin's Flow in ViewModels: it's complicated - Christophe Beyls
Using StateFlow as trigger in a ViewModel. A common scenario is to use a trigger-based approach to load data in a ViewModel: every...
Read more >Developers - StateFlow .combine usage with .asLiveData -
StateFlow .combine usage with .asLiveData. Kotlin. 25 November 2020 Posted by carterhudson. I'm using StateFlow under the hood, but still exposing LiveData ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
It is not expected, but it may, indeed, change the behavior, just like putting
delay
makes it work in this particular test case. This is definitely not a general solution and does not guarantee anything if you write a longer test. Data propagation through a flow is, in general, asynchronous. On the other hand, puttingadvanceUntilIdle()
after updates guarantees that all data propagation had finished and you can safely assert the derived values.Makes sense, thanks for the explanations! I think we can close this 😄