I recently discovered Flows in Kotlin and ever since been trying to optimize the code and making it more readable by avoiding MediatorLiveData and friends.
I try to use Flow in my back ends and finally present it as LiveData to the UI. However, I am having an issue with LiveData unsubscribing after a timeout, which causes the cold flows to recalculate (and make a new network request) each time the timeout is exceeded. Is there any way around it?
Here's the problem:
private val storeProducts = combine(_currentBasket, _currentProduct) { basket, product ->
// network operation
}
val storeProductsLive = storeProducts.asLiveData()
From the above example, my UI observes it as a normal livedata observable. When I rotate my screen, everything works fine and the last value is returned. However, if I navigate to a subfragment and go back after 5s or if I go out of the app and return later, the network operation is done again. the .asLiveData() specifies a default timeout of 5s, after that the Flow is cancelled.
My current workaround:
private val productsState = MutableStateFlow<List<Product>>(emptyList())
init {
viewModelScope.launch {
storeProducts.collect {
productsState.value = it
}
}
}
However, this is quite hacky and it means the observer is always registered, regardless whether the UI actually cares about it. Any way around it?
UPDATE Within an hour, I found another workaround (described here: https://github.com/Kotlin/kotlinx.coroutines/issues/2140 ):
val storeProductsLive: LiveData<List<Product>> by lazy {
MutableStateFlow<List<Product>>(emptyList()).apply {
viewModelScope.launch {
storeProducts.collect { value = it }
}
}.asLiveData()
}
Is this the recommended way?