Reputation: 6008
In my use case I have a fragment with a data subscription, which fetch data per 3 seconds automatically. And when the fragment is destroyed, this subscription will be stopped because no subscriber using this data subscription.
However, if I opened a popup dialog fragment from this fragment and the dialog fragment is connected with data subscription. I will get a weird user experience that user might wait up to 3 seconds to see the data. I found out that the first fragment is not on paused and it will treat the first call flag as invalid and delay 3 seconds to emit the new data.
case:
Fragment A -> Dialog Fragment B
Here is my repository class with a temporary solution using simple flag and while loop. I am using flow, how could i send the last result to the new observer so they dun have to wait up to 3 seconds to receive new data?
Appreciate any advice or comments
DataRepository.kt
class DataRepository {
private val isCalledFirstTime = AtomicBoolean(true)
private val latestData by lazy {
flow {
while (true) {
if (hasSubscription()) {
try {
val response = restService.getData()
emit(response)
isCalledFirstTime.set(false)
} catch (e: Exception) {
logger.e(e)
}
}
if (isCalledFirstTime.get()) {
delay(200)
} else {
var count = 0
do {
delay(200)
} while (count++ < (200 / 3000) && !isCalledFirstTime.get())
}
}
}
}
fun observeData() = latestData
}
Upvotes: 3
Views: 5161
Reputation: 4811
Because your latestData is a cold flow you have to convert it to a hot flow like StateFlow or SharedFlow to get the cached value with the same publisher.
To make that, we will use Flow.shareIn
operator
class DataRepository() {
private val repoScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private val latestData by lazy {
flow {
// Your code
}.shareIn(
repoScope,
replay = 1,
started = SharingStarted.WhileSubscribed()
)
}
}
replay
: How many values do you want to get from cached when starting subscribed.More information here : Making cold flows hot using shareIn
Upvotes: 1
Reputation: 7642
I think your LiveData
might become inactive, when your view gets into PAUSED state.
I'd double check if this is the case, with LiveData.onInactive()
Also I wouldn't convert it to LiveData
I'd go with observing simply the flow:
repository.observeData().flowWithLifecycle(this, Lifecycle.State.STARTED)
.onEach {
...
}
.launchIn(lifecycleScope) // or viewLifecycleScope
Upvotes: 0