我正在尝试使用 DataStore
存储值。
class BasicDataStore(context: Context) :
PrefsDataStore(
context,
PREF_FILE_BASIC
),
BasicImpl {
override val serviceRunning: Flow<Boolean>
get() = dataStore.data.map { preferences ->
preferences[SERVICE_RUNNING_KEY] ?: false
}
override suspend fun setServiceRunningToStore(serviceRunning: Boolean) {
dataStore.edit { preferences ->
preferences[SERVICE_RUNNING_KEY] = serviceRunning
}
}
companion object {
private const val PREF_FILE_BASIC = "basic_preference"
private val SERVICE_RUNNING_KEY = booleanPreferencesKey("service_running")
}
}
@Singleton
interface BasicImpl {
val serviceRunning: Flow<Boolean>
suspend fun setServiceRunningToStore(serviceRunning: Boolean)
}
在 Service
中,试图监控该值,这是相应的代码:
private fun monitorNotificationService() {
Log.d("d--mua-entry-service","entry")
CoroutineScope(Dispatchers.IO).launch {
Log.d("d--mua-entry-service","entry scope")
basicDataStore.serviceRunning.collect{
Log.d("d--mua-entry-service","$it current status - collect")
}
basicDataStore.serviceRunning.onEach {
Log.d("d--mua-entry-service","$it current status - on each")
}
}
}
在 EntryService
中:
init {
basicDataStore = BasicDataStore(this)
}
但似乎 onEach 根本不起作用。并且 collect 只工作一次,这是应该的。那么我应该如何监控/观察流量呢?
日志:
2021-03-25 20:41:49.462 30761-30761/com.mua.roti D/d--mua-entry-service: entry
2021-03-25 20:41:49.465 30761-30900/com.mua.roti D/d--mua-entry-service: entry scope
2021-03-25 20:41:49.471 30761-30901/com.mua.roti D/d--mua-entry-service: false current status - collect
最佳答案
我没有使用过 DataStore,但我希望 Flow 是无限的,这意味着它永远不会完成收集,直到您取消协程。因此,将永远不会访问第一次调用 collect()
之后的任何代码。此外,当您调用 onEach
时,它只会返回另一个 Flow。在您收集返回的 Flow 之前,不会调用 onEach
中的代码。 onEach
用于将副作用添加到您稍后将进行的收集中。或者设置在使用 launchIn
收集它时要做什么。
创建一个不存储在属性中以供取消的 CoroutineScope 是一种代码味道。范围的要点是当关联组件的生命周期结束时,您可以取消它。如果您创建它并像这样丢弃您的引用,您将永远无法取消它的子级,因此调用 collect
将泄漏周围的类。如果您在 Android 上工作,您很少需要创建任何 CoroutineScope,因为该框架为各种生命周期组件(如 Activity、Fragment、ViewModel 和 LifecycleService)提供了作用域。
关于kotlin flow onEach 没有被触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66802018/