如何立即启动 lifecycle.whenResumed 协程,以便在返回之前开始流收集?
How to launch lifecycle.whenResumed coroutine immediately so flow-collection starts before returning?
我在 whenResumed 中收听一个流程,因此仅在应用程序恢复时收集事件。但是,我想确保在 运行 可能发送必须收集的事件的代码之前我已经启动了监听器。
init {
lifecycleScope.launchWhenResumed {
stateUpdates.collect { onUpdate(it) }
}
// Now do stuff that might trigger event, which I want to collect above.
// This does not have to be in init {}, an initialize() is fine
doMyThing()
}
我知道我可以将 sharedFlow 与缓存一起使用,但对于我的用例,缓存可能有问题。
--
我知道我可以执行以下操作,其中第 1 行立即执行,但这里再次调度第 2 行,因此稍后执行:
CoroutineScope(Dispatchers.Main).launch(start = CoroutineStart.UNDISPATCHED) {
// 1
lifecycle.whenResumed {
// 2
}
}
==== 更新 3. 2022 年 3 月
感谢 IR42 提供有关选项的有用信息。我实际上是在安排许多不同类型的收集器,然后做我的事。
init {
lifecycleScope.launchWhenResumed {
launch { stateUpdates1.collect { onUpdate1(it) } }
launch { stateUpdates2.collect { onUpdate2(it) } }
launch { stateUpdates3.collect { onUpdate3(it) } }
launch { stateUpdates4.collect { onUpdate4(it) } }
launch { stateUpdates5.collect { onUpdate5(it) } }
}
// Now do stuff that might trigger event, which I want to collect above.
// This does not have to be in init {}, an initialize() is fine
doMyThing()
}
我想要一个很好的惯用方法来做到这一点。我不知道如何使用 onSubscription() 执行此操作,但我很感谢您的输入,因为它对我来说是新的。
我想我找到了解决办法。它需要在协程内部产生,所以其他所有调度在同一个 Dispatcher 上的协程(例如主线程)都有机会 运行.
lifecycleScope.launchWhenResumed {
launch { stateUpdates1.collect { onUpdate1(it) } }
launch { stateUpdates2.collect { onUpdate2(it) } }
}
// do other stuff if needed here, or join the two coroutines
lifecycleScope.launchWhenResumed {
yield()
// Do my thing, that might result in state-update
doMyThing()
}
如果 yield() + doMyThing()
在同一个协程中,上面的方法同样有效。
见Kotlin Coroutine Yield
还有这个问题
请注意,我之前有一个错误的答案涉及 运行Blocking { }。 RunBlocking 阻塞了我的 UI-thread 这是糟糕的设计,即使代码立即执行也是如此。它也不会在 运行Blocking 内部执行其他预定协程,这不是我所期望的。我从答案中删除了它,因为它不应该在生产代码中使用。另见
而不是这样做:
runBlocking {
lifecycleScope.launchWhenResumed {
stateUpdates.collect { onUpdate(it) }
}
yield()
}
这样做,它不那么脆弱:
lifecycleScope.launchWhenResumed {
yield()
stateUpdates.collect { onUpdate(it) }
}
不过,它仍然有点脆弱,因为它依赖于提交协程的顺序。
您可以使用onSubscription
lifecycleScope.launchWhenResumed {
stateUpdates
.onSubscription {
// Do my thing, that might result in state-update
}
.collect { onUpdate(it) }
}
我在 whenResumed 中收听一个流程,因此仅在应用程序恢复时收集事件。但是,我想确保在 运行 可能发送必须收集的事件的代码之前我已经启动了监听器。
init {
lifecycleScope.launchWhenResumed {
stateUpdates.collect { onUpdate(it) }
}
// Now do stuff that might trigger event, which I want to collect above.
// This does not have to be in init {}, an initialize() is fine
doMyThing()
}
我知道我可以将 sharedFlow 与缓存一起使用,但对于我的用例,缓存可能有问题。
--
我知道我可以执行以下操作,其中第 1 行立即执行,但这里再次调度第 2 行,因此稍后执行:
CoroutineScope(Dispatchers.Main).launch(start = CoroutineStart.UNDISPATCHED) {
// 1
lifecycle.whenResumed {
// 2
}
}
==== 更新 3. 2022 年 3 月
感谢 IR42 提供有关选项的有用信息。我实际上是在安排许多不同类型的收集器,然后做我的事。
init {
lifecycleScope.launchWhenResumed {
launch { stateUpdates1.collect { onUpdate1(it) } }
launch { stateUpdates2.collect { onUpdate2(it) } }
launch { stateUpdates3.collect { onUpdate3(it) } }
launch { stateUpdates4.collect { onUpdate4(it) } }
launch { stateUpdates5.collect { onUpdate5(it) } }
}
// Now do stuff that might trigger event, which I want to collect above.
// This does not have to be in init {}, an initialize() is fine
doMyThing()
}
我想要一个很好的惯用方法来做到这一点。我不知道如何使用 onSubscription() 执行此操作,但我很感谢您的输入,因为它对我来说是新的。
我想我找到了解决办法。它需要在协程内部产生,所以其他所有调度在同一个 Dispatcher 上的协程(例如主线程)都有机会 运行.
lifecycleScope.launchWhenResumed {
launch { stateUpdates1.collect { onUpdate1(it) } }
launch { stateUpdates2.collect { onUpdate2(it) } }
}
// do other stuff if needed here, or join the two coroutines
lifecycleScope.launchWhenResumed {
yield()
// Do my thing, that might result in state-update
doMyThing()
}
如果 yield() + doMyThing()
在同一个协程中,上面的方法同样有效。
见Kotlin Coroutine Yield
还有这个问题
请注意,我之前有一个错误的答案涉及 运行Blocking { }。 RunBlocking 阻塞了我的 UI-thread 这是糟糕的设计,即使代码立即执行也是如此。它也不会在 运行Blocking 内部执行其他预定协程,这不是我所期望的。我从答案中删除了它,因为它不应该在生产代码中使用。另见
而不是这样做:
runBlocking {
lifecycleScope.launchWhenResumed {
stateUpdates.collect { onUpdate(it) }
}
yield()
}
这样做,它不那么脆弱:
lifecycleScope.launchWhenResumed {
yield()
stateUpdates.collect { onUpdate(it) }
}
不过,它仍然有点脆弱,因为它依赖于提交协程的顺序。
您可以使用onSubscription
lifecycleScope.launchWhenResumed {
stateUpdates
.onSubscription {
// Do my thing, that might result in state-update
}
.collect { onUpdate(it) }
}