Сопрограмма withContext не работает. Использование Kotlin в Android - PullRequest
0 голосов
/ 18 июня 2020

Я обдумывал это уже некоторое время и просто не могу заставить его работать.

Короче говоря, у меня есть действие Spla sh, из которого я вызываю другое действие, которое содержит мою ViewModel. Простыми словами, ViewModel просто должен последовательно запускать функцию A (которая ниже getfbdata; это сетевой вызов). И только после того, как эта функция завершится, она должна запустить функцию B (которая ниже - dosavefbdata; сохранить информацию в БД). Опять же, он должен дождаться завершения функции B, прежде чем запускать функцию основного потока, функцию C (которая сначала подтверждается ниже; она проверяет, завершилась ли функция B, получая результат от функции B (dosavefbdata ниже). Если функция C положительный, он закрывает действие Spla sh.

Достаточно сказать, что ничего из вышеперечисленного не работает. Результаты Println показывают, что все функции выполнялись последовательно, не дожидаясь завершения каждой. Наконец, SplashActivity () Вызов .killActivity () для функции C не работал.

Примечание: withContext не требует await () для приостановленных функций, верно? Я также пробовал использовать viewModelScope.asyn c вместо viewModelScope. Запуск.

Буду очень признателен за вашу помощь. Заранее спасибо.


* В SplashActivity:

fun killActivity(){
    finish()
}

* В onCreate (SplashActivity):

CoroutingClassViewModel (мой c). 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")
        }
    }
}

1 Ответ

1 голос
/ 18 июня 2020
  • Используйте AndroidViewModel, если вы хотите, чтобы в нем было Context:

    class CoroutingClassViewModel(myc: Application) : AndroidViewModel(myc) { ... }
    
  • In onCreate метод of SplashActivity activity создают экземпляр модели представления следующим образом:

    val vm = ViewModelProvider(this)[CoroutingClassViewModel::class.java]
    vm.initialize()
    
  • В классе CoroutingClassViewModel создайте объект LiveData для уведомления активности о завершении операций:

    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()
    
...