简体   繁体   English

Kotlin 流程:当我有新订阅者时,如何从订阅中获取缓存数据?

[英]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

  • FragmentA: onResume片段A:onResume
  • FragmentB: onResume片段B:onResume

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.

相关问题 如何在流中使用来自另一个流数据的数据? (科特林流程) - How can I use data from another flow data in flow? (Kotlin Flow) 如何将项目发送到 Kotlin.Flow(如 Behaviorsubject) - How can I send items to a Kotlin.Flow (like a Behaviorsubject) 我应该先在 kotlin 返回什么? - What should I have to return at kotlin Flow first function? 当 SharedPreferences 发生变化时,我想使用 Kotlin Flow 来更新我的 UI - I want to use Kotlin Flow to update my UI when SharedPreferences have changed "如何更新android协程中的流源数据?" - How can I update the flow source data in android coroutine? 如何使用 Kotlin Flow 从异步回调中发出数据? - How to emit data from an asycnhronous callback using Kotlin Flow? 合并来自 Kotlin Flow/LiveData 的数据 - Combine data from Kotlin Flow/LiveData Android - 如何从 kotlin 流中读取值? - Android - How to read a value from a kotlin flow? 如何使用Kotlin Flow提供的flatMapMerge? - How to use flatMapMerge from kotlin flow? 仅当订阅者计数从 0 变为 1 或从 1 变为 0 时,如何触发源 observable 的订阅副作用 - How to have subscription side effects of source observable trigger only when the subscriber count changes from 0 to 1 or from 1 to 0
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM