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
.
3 Réponses :
Tous ces éléments de contexte coroutine ont une propriété 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: 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 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]
companion object Key : Key<CoroutineName>
CoroutineName dans
coroutineContext [CoroutineName]
dans IDEA et voyez la déclaration vous-même.
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.
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
.
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 a >.Lorsque vous, disons,
lancez
une nouvelle coroutine, lecoroutineContext
est à votre disposition en tant que membre duCoroutineScope
qui est le récepteur sur le bloc que vous passez aulancement
. Cependant, ce que je veux savoir, c'est comment nous pouvons accéder àcoroutineContext [CoroutineName]
. CommentCoroutineName
est-il disponible dans la portée actuelle pour que nous l'utilisions comme index dans la carte fournie parcoroutineContext
?