从 android 和协程中的流中收集值的正确方法
Proper way to collect values from flow in android and coroutines
我是 Kotlin 协程和流程的新手。我正在使用数据存储来存储一些布尔数据,从数据存储读取数据的唯一方法是根据文档使用流程。
我的 ViewModel 中有这段代码
fun getRestroProfileComplete(): Boolean {
var result = false
viewModelScope.launch {
readRestroDetailsValue.collect { pref ->
result = pref.restroProfileCompleted
}
}
Log.d(ContentValues.TAG, "getRestroProfileComplete outside: $result")
return result
}
在我的片段 onCreateView 方法中,这段代码
if(restroAdminViewModel.getRestroProfileComplete()){
Log.d(TAG, "Profile Completed")
profileCompleted(true)
}else{
Log.d(TAG, "Profile not completed ")
profileCompleted(false)
}
有时我从数据存储中获取数据,但有时它总是错误的。
我知道 getRestroProfileComplete 方法函数不会等待启动代码块完成并给出默认的错误结果。
最好的方法是什么?
您正在启动一个异步协同程序(带启动),然后,无需等待它完成其工作,您就可以 return 结果变量中的任何内容。有时会设置结果,有时不会,具体取决于数据存储加载首选项所需的时间。
如果您需要在非协程上下文中使用首选项值,则必须使用 runBlocking
,如下所示:
fun getRestroProfileComplete(): Boolean {
val result = runBlocking {
readRestroDetailsValue.collect { pref ->
pref.restroProfileCompleted
}
}
Log.d(ContentValues.TAG, "getRestroProfileComplete outside: $result")
return result
}
但是,这根本不是一件好事!您应该公开一个流程并从片段中使用该流程,这样您就不会阻塞主线程并且您的 UI 可以对偏好更改做出反应。
fun getRestroProfileComplete(): Flow<Boolean> {
return readRestroDetailsValue.map { pref ->
pref.restroProfileCompleted
}
}
并在片段的 onCreateView 中启动协程:
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
restroAdminViewModel.getRestroProfileComplete().collect { c ->
if(c) {
Log.d(TAG, "Profile Completed")
profileCompleted(true)
} else {
Log.d(TAG, "Profile not completed ")
profileCompleted(false)
}
}
(这将持续监控首选项,您可以用流程做其他事情,比如用 .first { it }
获取第一个 true
元素)
我是 Kotlin 协程和流程的新手。我正在使用数据存储来存储一些布尔数据,从数据存储读取数据的唯一方法是根据文档使用流程。
我的 ViewModel 中有这段代码
fun getRestroProfileComplete(): Boolean {
var result = false
viewModelScope.launch {
readRestroDetailsValue.collect { pref ->
result = pref.restroProfileCompleted
}
}
Log.d(ContentValues.TAG, "getRestroProfileComplete outside: $result")
return result
}
在我的片段 onCreateView 方法中,这段代码
if(restroAdminViewModel.getRestroProfileComplete()){
Log.d(TAG, "Profile Completed")
profileCompleted(true)
}else{
Log.d(TAG, "Profile not completed ")
profileCompleted(false)
}
有时我从数据存储中获取数据,但有时它总是错误的。
我知道 getRestroProfileComplete 方法函数不会等待启动代码块完成并给出默认的错误结果。
最好的方法是什么?
您正在启动一个异步协同程序(带启动),然后,无需等待它完成其工作,您就可以 return 结果变量中的任何内容。有时会设置结果,有时不会,具体取决于数据存储加载首选项所需的时间。
如果您需要在非协程上下文中使用首选项值,则必须使用 runBlocking
,如下所示:
fun getRestroProfileComplete(): Boolean {
val result = runBlocking {
readRestroDetailsValue.collect { pref ->
pref.restroProfileCompleted
}
}
Log.d(ContentValues.TAG, "getRestroProfileComplete outside: $result")
return result
}
但是,这根本不是一件好事!您应该公开一个流程并从片段中使用该流程,这样您就不会阻塞主线程并且您的 UI 可以对偏好更改做出反应。
fun getRestroProfileComplete(): Flow<Boolean> {
return readRestroDetailsValue.map { pref ->
pref.restroProfileCompleted
}
}
并在片段的 onCreateView 中启动协程:
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
restroAdminViewModel.getRestroProfileComplete().collect { c ->
if(c) {
Log.d(TAG, "Profile Completed")
profileCompleted(true)
} else {
Log.d(TAG, "Profile not completed ")
profileCompleted(false)
}
}
(这将持续监控首选项,您可以用流程做其他事情,比如用 .first { it }
获取第一个 true
元素)