web-dev-qa-db-fra.com

Migrer vers les coroutines Kotlin dans Android avec Kotlin 1.3

Que dois-je changer dans mon build.gradle fichier ou importation dans les classes pour utiliser des fonctions coroutines stables dans mon Android avec Kotlin 1.3?

Fragment de coroutines dans mon build.gradle

implementation "org.jetbrains.kotlin:kotlin-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlin:kotlin-coroutines-Android:$coroutines_version"

Bien sûr, j'utilise Android Studio 3.3 Preview

10
Patryk Kubiak

Dans build.gradle, Changez une bibliothèque en

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-Android:1.1.1'.

Supprimer, si a été ajouté:

kotlin {
    experimental {
        coroutines "enable"
    }
}

Dans le code, changez launch en GlobalScope.launch(Dispatchers.IO) ou GlobalScope.launch(Dispatchers.Main).

[~ # ~] mise à jour [~ # ~]

Veuillez utiliser le contexte coroutine local au lieu de la portée globale (voir, par exemple, http://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html ).

Pour l'activité

Voir https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md .

Implémentez CoroutineScope:

class YourActivity : AppCompatActivity(), CoroutineScope {

Ajoutez une variable locale job et initialisez-la:

private lateinit var job: Job

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

    job = Job()
}

Créez un contexte de coroutine et annulez-le lors de la destruction d'activité:

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

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

Pour le fragment (le même que dans Activity)

Implémentez CoroutineScope:

class YourFragment : Fragment(), CoroutineScope {

Créez une variable locale job et initialisez-la dans onCreate(). (J'ai essayé d'écrire private val job: Job = Job(), mais j'ai rencontré un problème: dans ViewPager, vous créerez Fragments et leurs travaux. Comme nous annulerons le job dans onDestroy() lors du glissement dans ViewPager, nous devons recréer le travail).

private lateinit var job: Job

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

    ...
    job = Job()
}

Créez un contexte de coroutine et annulez-le lors de la destruction des fragments:

override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job // You can use different variants here. 

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

Un exemple de lancement

Utilisez launch comme d'habitude:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    launch {
        // Wait for result of I/O operation without blocking the main thread.
        withContext(Dispatchers.IO) {
            interactor.getCountry().let {
                countryName = it.name
            }
        }

        // Update views in the UI thread.
        country.updateCaption(countryName)
    }
}

Dans mon cas, un problème s'est produit lorsque j'ai utilisé des demandes d'API avec des rappels habituels. Un launch intérieur à l'intérieur d'un rappel n'a pas été appelé. J'ai donc réécrit ce code avec des interacteurs.

24
CoolMind

Mon coéquipier m'a aidé à trouver la solution. J'ai dû augmenter la version coroutines à 1.0.0-RC1. Pour tous ceux qui ne connaissent peut-être pas les changements dans l'utilisation des coroutines Android:

  • J'ai dû changer le contexte de l'interface utilisateur de coroutine en Dispatchers.
  • J'ai utilisé une ancienne version expérimentale de coroutines (0.23 peut-être) donc pour tous ceux qui ne savent pas - maintenant le lancement est obsolète et vous devriez utiliser à la place une concurrence structurée (par exemple coroutineScope).
  • Désormais, la fonction asynchrone ne peut pas être exécutée en dehors de la portée.

J'espère que j'aiderai quelqu'un. Ne perdez pas de temps. Bonne programmation!

5
Patryk Kubiak