1
votes

Comment les éléments de la coroutine Kotlin sont-ils accessibles dans le contexte actuel?

J'essaie d'apprendre comment fonctionnent les coroutines dans Kotlin. J'ai lu plusieurs articles en ligne, dont celui-ci - https://proandroiddev.com/demystifying-coroutinecontext- 1ce5b68407ad - mais je me trouve toujours un peu confus sur la façon dont les éléments coroutine dans le contexte actuel peuvent être accédés. Voici la partie qui me trouble.

Les éléments du contexte actuel peuvent être obtenus en utilisant la propriété en lecture seule de suspension coroutineContext de niveau supérieur.

println ("Exécution dans $ {coroutineContext [CoroutineName]}")

Dans ce cas, CoroutineName est une référence à la clé qui correspond à l'élément CoroutineName . Je comprends que la méthode get sur le coroutineContext examine le type générique de la clé qui lui est fournie - dans ce cas, CoroutineName - pour obtenir l'élément approprié. Ce que j'essaie de comprendre, c'est comment CoroutineName , ou d'ailleurs Job , CoroutineExceptionHandler ou CoroutineDispatcher sont même disponibles pour se référer dans la portée actuelle, quand ils ne sont pas des propriétés du récepteur CoroutineScope .


2 commentaires

Je ne sais pas exactement de quoi vous parlez, mais voici une supposition: lorsque vous déréférencer la propriété globale coroutineContext , vous avez touché un élément intrinsèque de Kotlin qui "par magie", d'une manière non explicable par inspecter le code source, vous fournit le contexte coroutine actuellement en vigueur. Code source ici .


Lorsque vous, disons, lancez une nouvelle coroutine, le coroutineContext est à votre disposition en tant que membre du CoroutineScope qui est le récepteur sur le bloc que vous passez au lancement . Cependant, ce que je veux savoir, c'est comment nous pouvons accéder à coroutineContext [CoroutineName] . Comment CoroutineName est-il disponible dans la portée actuelle pour que nous l'utilisions comme index dans la carte fournie par coroutineContext ?


3 Réponses :


0
votes

Tous ces éléments de contexte coroutine ont une propriété key utilisée pour adresser les éléments dans un contexte coroutine (qui est une sorte d'ensemble adressable). CoroutineName , comme d'autres éléments de contexte, définissent une clé comme un objet:

coroutineContext[CoroutineName]
coroutineContext[CoroutineName.Key]

Dans Kotlin , vous pouvez accéder à l'objet compagnon de la classe en utilisant le nom de la classe:

L'objet compagnon est un singleton, et ses membres sont accessibles directement via le nom de la classe contenant (bien que vous puissiez également insérer le nom de l'objet compagnon si vous voulez être explicite sur l'accès à l'objet compagnon) p>

Donc, je pense que ces deux expressions seront les mêmes:

companion object Key : Key<CoroutineName>

Une autre excellente question sur les objets compagnons sur SO: Quel est l'intérêt de nommer un objet compagnon dans kotlin

BTW, vous pouvez simplement ctrl + cliquer sur le CoroutineName dans coroutineContext [CoroutineName] dans IDEA et voyez la déclaration vous-même.


0 commentaires

0
votes

L'implémentation de la propriété globale coroutineContext est intrinsèque, ce qui signifie qu'aucune promesse n'est faite sur la manière dont elle est réellement implémentée.

Mais sur la JVM, la propriété est essentiellement une variable locale de thread. Lorsqu'une coroutine est suspendue, le contexte de coroutine actuel est mémorisé dans l'objet Continuation qui est créé. Lorsque la coroutine est reprise, le contexte est recopié de la continuation de reprise vers la variable locale de thread à laquelle la propriété coroutineContext fait référence.


0 commentaires

0
votes

Voici un code simple que vous pouvez exécuter pour clarifier votre compréhension:

StandaloneCoroutine{Active}@b4642b3
kotlinx.coroutines.GlobalScope@72445c73

Il imprimera

fun main() {
    GlobalScope.launch {
        println(this)
        println(GlobalScope)
    }
    Thread.sleep(100)
}

ce qui devrait être clair pour que la portée dans laquelle vous lancez une coroutine n'est pas la portée qui est le récepteur de votre bloc de création de coroutine. La portée que vous obtenez a été créée par la fonction launch , qui l'a remplie avec le nom et tout ce que vous voyez.

La partie la plus magique de ce mécanisme est que coroutineContext n'est pas seulement disponible dans launch , mais dans n'importe quel suspend fun , en tant que propriété globale. Il évalue le même contexte que celui que vous voyez dans le bloc lancement .


0 commentaires