web-dev-qa-db-fra.com

La fonction de suspension 'callGetApi' ne doit être appelée qu'à partir d'une coroutine ou d'une autre fonction de suspension

J'appelle la fonction suspendue de onCreate (...)

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    ...
    callGetApi()
}

et la fonction suspendue est: -

suspend fun callGetApi() {....}

Mais l'erreur apparaît la fonction de suspension 'callGetApi' ne doit être appelée qu'à partir d'une coroutine ou d'une autre fonction de suspension

10
Santanu Sur

La fonction de suspension ne doit être appelée que depuis coroutine. Cela signifie que vous devez utiliser un générateur de coroutine, par exemple launch. Par exemple:

class Activity : AppCompatActivity(), CoroutineScope {
    private var job: Job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        launch {
            val result =  callGetApi()
            onResult(result) // onResult is called on the main thread
        }
    }

    fun onResult(result: ...) {}
}

Utiliser Dispatchers.Main in Android ajoute une dépendance au build.gradle fichier:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-Android:1.0.1'
11
Sergey

La réponse ci-dessus a fonctionné, mais je l'ai résolue sans hériter de la classe CoroutineScope en utilisant simplement .... gradle.build

  dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M2")
  }

Activity.kt

  import kotlinx.coroutines.GlobalScope
  import kotlinx.coroutines.Dispatchers

  GlobalScope.launch (Dispatchers.Main) { callGetApi() }

Dispatchers.Main est important car vous ne pouvez pas mettre à jour l'interface utilisateur dans un autre thread que principal.

Mais il est recommandé d'hériter de CoroutineScope pour maintenir le cycle de vie de l'activité et onDestroy de l'activité pour tuer le travail

5
Santanu Sur

On dirait que la façon la plus élégante de le faire en juillet 2019 , est celle décrite ici :

import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch

class Activity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super...

        lifecycleScope.launch {
            val result =  callGetApi()
            onResult(result) 
        }
    }
}

N'oubliez pas d'ajouter la bibliothèque correspondante:

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha02"
1
Kipr