withContext 协程不工作。在 Android 中使用 Kotlin
The withContext coroutine is not working. Using Kotlin in Android
我已经考虑了一段时间了,但就是无法让它发挥作用。
简而言之,我有一个 Splash Activity,我从那里调用另一个包含我的 ViewModel 的 activity。 ViewModel简单来说只需要顺序运行函数A(就是下面的getfbdata,是网络调用。)。只有在这个函数完成后,它才应该 运行 函数 B(下面是 dosavefbdata;将信息保存到 DB。)。同样,它应该等待函数 B 完成,然后 运行 调用主线程函数,函数 C(下面首先确认;它通过从函数 B(下面的 dosavefbdata)获取结果来检查函数 B 是否已完成。如果函数 C 为正,则关闭 Splash activity.
可以说,none 以上作品。 Println 结果显示所有函数都是 运行 顺序执行的,无需等待每个函数完成。最后,SplashActivity().killActivity() 对函数 C 的调用无效。
注意:withContext 不需要 await() 挂起的函数,对吗?我也尝试使用 viewModelScope.async 而不是 viewModelScope.launch.
非常感谢您的帮助。提前致谢。
*在飞溅Activity:
fun killActivity(){
finish()
}
*在onCreate(SplashActivity)下:
CoroutingClassViewModel(myc).initialize()
**
class CoroutingClassViewModel(val myc: Context): ViewModel() {
fun initialize() {
viewModelScope.launch(Dispatchers.Main) {
try {
val fbdata = withContext(Dispatchers.IO) { getfbdata() }
val test1 = withContext(Dispatchers.IO) { test1(fbdata) }
val savedfbdata = withContext(Dispatchers.IO) { dosavefbdata(fbdata,myc) }
val confirmfirst = { confirmfunc(savedfbdata,myc) }
println("ran savedfbdata.")
} catch (exception: Exception) {
Log.d(TAG, "$exception handled !")
}
}
}
fun confirmfunc(savedfbdata: Boolean, myc: Context){
if (savedfbdata==true){
SplashActivity().killActivity()
}
}
suspend fun getfbdata(): MutableList<FirebaseClass> {
return withContext(Dispatchers.IO) {
//perform network call
return@withContext fbdata
}
}
suspend fun dosavefbdata(fbdata: MutableList<FirebaseClass>,myc: Context): Boolean{
return withContext(Dispatchers.IO) {
//save to database
return@withContext true
}
}
suspend fun test1(fbdata: MutableList<FirebaseClass>){
return withContext(Dispatchers.IO) {
println("test1: fbdata is: $fbdata")
}
}
}
如果你想在其中包含Context
,请使用AndroidViewModel
:
class CoroutingClassViewModel(myc: Application) : AndroidViewModel(myc) { ... }
在SplashActivity
的onCreate
方法中activity像这样实例化视图模型:
val vm = ViewModelProvider(this)[CoroutingClassViewModel::class.java]
vm.initialize()
在 CoroutingClassViewModel
class 中创建 LiveData
对象以通知 activity 操作完成:
val completion = MutableLiveData<Boolean>()
fun confirmfunc(savedfbdata: Boolean, myc: Context) {
if (savedfbdata) {
completion.postValue(true)
}
}
在您的 SplashActivity 中使用此代码观察完成情况:
vm.completion.observe(this, Observer {
if (it) killActivity()
})
您对同一操作使用了两次withContext(Dispatchers.IO)
函数。不要那样做。例如在这段代码中:
val fbdata = withContext(Dispatchers.IO) { getfbdata() }
如果我们查看 getfbdata
函数,我们会看到函数 withContext(Dispatchers.IO)
已经在那里被调用。所以去掉重复调用:
val fbdata = getfbdata()
我对 withContext(Dispatcher.IO) 有同样的问题,我认为切换协程上下文不起作用,而实际上在初始屏幕上我在 Dispatcher.IO 上启动了超长操作,然后稍后当尝试使用相同的 Dispatcher.IO 它没有工作,或者换句话说,它等到启动画面中的第一个工作完成然后开始新工作。
我已经考虑了一段时间了,但就是无法让它发挥作用。
简而言之,我有一个 Splash Activity,我从那里调用另一个包含我的 ViewModel 的 activity。 ViewModel简单来说只需要顺序运行函数A(就是下面的getfbdata,是网络调用。)。只有在这个函数完成后,它才应该 运行 函数 B(下面是 dosavefbdata;将信息保存到 DB。)。同样,它应该等待函数 B 完成,然后 运行 调用主线程函数,函数 C(下面首先确认;它通过从函数 B(下面的 dosavefbdata)获取结果来检查函数 B 是否已完成。如果函数 C 为正,则关闭 Splash activity.
可以说,none 以上作品。 Println 结果显示所有函数都是 运行 顺序执行的,无需等待每个函数完成。最后,SplashActivity().killActivity() 对函数 C 的调用无效。
注意:withContext 不需要 await() 挂起的函数,对吗?我也尝试使用 viewModelScope.async 而不是 viewModelScope.launch.
非常感谢您的帮助。提前致谢。
*在飞溅Activity:
fun killActivity(){
finish()
}
*在onCreate(SplashActivity)下:
CoroutingClassViewModel(myc).initialize() **
class CoroutingClassViewModel(val myc: Context): ViewModel() {
fun initialize() {
viewModelScope.launch(Dispatchers.Main) {
try {
val fbdata = withContext(Dispatchers.IO) { getfbdata() }
val test1 = withContext(Dispatchers.IO) { test1(fbdata) }
val savedfbdata = withContext(Dispatchers.IO) { dosavefbdata(fbdata,myc) }
val confirmfirst = { confirmfunc(savedfbdata,myc) }
println("ran savedfbdata.")
} catch (exception: Exception) {
Log.d(TAG, "$exception handled !")
}
}
}
fun confirmfunc(savedfbdata: Boolean, myc: Context){
if (savedfbdata==true){
SplashActivity().killActivity()
}
}
suspend fun getfbdata(): MutableList<FirebaseClass> {
return withContext(Dispatchers.IO) {
//perform network call
return@withContext fbdata
}
}
suspend fun dosavefbdata(fbdata: MutableList<FirebaseClass>,myc: Context): Boolean{
return withContext(Dispatchers.IO) {
//save to database
return@withContext true
}
}
suspend fun test1(fbdata: MutableList<FirebaseClass>){
return withContext(Dispatchers.IO) {
println("test1: fbdata is: $fbdata")
}
}
}
如果你想在其中包含
Context
,请使用AndroidViewModel
:class CoroutingClassViewModel(myc: Application) : AndroidViewModel(myc) { ... }
在
SplashActivity
的onCreate
方法中activity像这样实例化视图模型:val vm = ViewModelProvider(this)[CoroutingClassViewModel::class.java] vm.initialize()
在
CoroutingClassViewModel
class 中创建LiveData
对象以通知 activity 操作完成:val completion = MutableLiveData<Boolean>() fun confirmfunc(savedfbdata: Boolean, myc: Context) { if (savedfbdata) { completion.postValue(true) } }
在您的 SplashActivity 中使用此代码观察完成情况:
vm.completion.observe(this, Observer { if (it) killActivity() })
您对同一操作使用了两次
withContext(Dispatchers.IO)
函数。不要那样做。例如在这段代码中:val fbdata = withContext(Dispatchers.IO) { getfbdata() }
如果我们查看
getfbdata
函数,我们会看到函数withContext(Dispatchers.IO)
已经在那里被调用。所以去掉重复调用:val fbdata = getfbdata()
我对 withContext(Dispatcher.IO) 有同样的问题,我认为切换协程上下文不起作用,而实际上在初始屏幕上我在 Dispatcher.IO 上启动了超长操作,然后稍后当尝试使用相同的 Dispatcher.IO 它没有工作,或者换句话说,它等到启动画面中的第一个工作完成然后开始新工作。