[英]Kotlin Flow : How can i get the cache data from subscription in flow when i have new subscriber?
In my use case I have a fragment with a data subscription, which fetch data per 3 seconds automatically.在我的用例中,我有一个带有数据订阅的片段,它每 3 秒自动获取数据。 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.
我会得到一个奇怪的用户体验,用户可能会等待长达 3 秒才能看到数据。 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.
我发现第一个片段没有暂停,它会将第一个调用标志视为无效并延迟 3 秒以发出新数据。
case:案子:
Fragment A -> Dialog Fragment B片段 A -> 对话框片段 B
Here is my repository class with a temporary solution using simple flag and while loop.这是我的存储库 class 使用简单标志和 while 循环的临时解决方案。 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?
我正在使用流,我如何将最后一个结果发送给新的观察者,这样他们就不得不等待最多 3 秒才能接收新数据?
Appreciate any advice or comments感谢任何建议或意见
DataRepository.kt数据存储库.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
}
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.因为您的 latestData 是冷流,所以您必须将其转换为像 StateFlow 或 SharedFlow 这样的热流,才能使用同一发布者获取缓存值。
To make that, we will use Flow.shareIn
operator为此,我们将使用
Flow.shareIn
运算符
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. replay
:开始订阅时,您希望从缓存中获取多少值。 More information here: Making cold flows hot using shareIn此处的更多信息: 使用 shareIn 使冷流变热
I think your LiveData
might become inactive, when your view gets into PAUSED state.我认为当您的视图进入PAUSED state 时,您的
LiveData
可能会变为非活动状态。
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:我会仔细检查是否是这种情况,使用LiveData.onInactive()我也不会将其转换为
LiveData
我会 go 只观察流程:
repository.observeData().flowWithLifecycle(this, Lifecycle.State.STARTED)
.onEach {
...
}
.launchIn(lifecycleScope) // or viewLifecycleScope
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.