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) { ... }
    
  • SplashActivityonCreate方法中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 它没有工作,或者换句话说,它等到启动画面中的第一个工作完成然后开始新工作。