Hey guys, I have a question regarding coroutines f...
# coroutines
d
Hey guys, I have a question regarding coroutines flow. I have a typical Repository use case where I would like to return a Flow<List<Something>> of data (in memory cache), but when that data is empty, I need to get (and store) from somewhere else (Remote), so for following collectors, I should replay the same value, and not call remote again. I was searching for a Flow function that would help me with that, but I need to make the Flow collectors wait so the remote call should be done only once. Is there an easy way to achieve this? What I tried:
Copy code
class Repository {
	private val idsFlow = MutableStateFlow<List<String>>(emptyList())

	fun getMyFlow(): Flow<List<String>> = idsFlow.onSubscription { 
		if (idsFlow.value.isEmpty() idsFlow.value = getRemoteIds()) 
	}

	private suspend fun getRemoteIds(): List<String> {
		delay(2_000)
		return listOf("1", "2")
	}

	.. 
	// other functions that can modify myFlow (ie. add / delete / update an item from it)
}
problem is, if multiple collectors are subscribing fast enough, getRemoteData gets called multiple times (which I want to avoid).
s
Is each collector calling
getMyGlow
separately? I think maybe you just need to move the
onSubscription
so that it gets called once when you create the
idsFlow
, rather than calling it every time
getMyFlow
is called.
d
regarding your first question, yes I do, but your proposed code doesn’t change much,
onSubscription
is called for each collector. (I tested it and getRemoteIds gets called for each collector).
n
If you want to share work, you need a scope and you either need to put the shared work upstream of
shareIn
or
stateIn
or you need to launch it yourself.
Copy code
launch {
    idsFlow.subscriptionCount.first { it > 0 }
    idsFlow.value = getRemoteIds()
}
I'd be careful of this setup. Nothing stops the list from being edited before the results have loaded. I'd recommend starting out without a value, using a sealed class with a Loading object or just using null to indicate that the real data hasn't arrived yet.