@@ -104,8 +104,9 @@ context object for your favourite UI library, even if it is not included out of
104104* [ Blocking operations] ( #blocking-operations )
105105 * [ The problem of UI freezes] ( #the-problem-of-ui-freezes )
106106 * [ Blocking operations] ( #blocking-operations )
107- * [ Lifecycle] ( #lifecycle )
108- * [ Using coroutine parent-child hierarchy] ( #using-coroutine-parent-child-hierarchy )
107+ * [ Advanced topics] ( #advanced-topics )
108+ * [ Lifecycle and coroutine parent-child hierarchy] ( #lifecycle-and-coroutine-parent-child-hierarchy )
109+ * [ Starting coroutine in UI event handlers without dispatch] ( #starting-coroutine-in-ui-event-handlers-without-dispatch )
109110
110111<!-- - END_TOC -->
111112
@@ -538,11 +539,11 @@ Note, that because the `fib` function is invoked from the single actor in our co
538539computation of it at any given time, so this code has a natural limit on the resource utilization.
539540It can saturate at most one CPU core.
540541
541- ## Lifecycle
542+ ## Advanced topics
542543
543- This section outlines an approach to life-cycle management with coroutines .
544+ This section covers various advanced topics .
544545
545- ### Using coroutine parent-child hierarchy
546+ ### Lifecycle and coroutine parent-child hierarchy
546547
547548A typical UI application has a number of elements with a lifecycle. Windows, UI controls, activities, views, fragments
548549and other visual elements are created and destroyed. A long-running coroutine, performing some IO or a background
@@ -618,6 +619,80 @@ Parent-child relation between jobs forms a hierarchy. A coroutine that performs
618619the view and in its context can create further children coroutines. The whole tree of coroutines gets cancelled
619620when the parent job is cancelled. An example of that is shown in
620621[ "Children of a coroutine"] ( ../coroutines-guide.md#children-of-a-coroutine ) section of the guide to coroutines.
622+
623+ ### Starting coroutine in UI event handlers without dispatch
624+
625+ Let us write the following code in ` setup ` to visualize the order of execution when coroutine is launched
626+ from the UI thread:
627+
628+ <!-- - CLEAR -->
629+
630+ ``` kotlin
631+ fun setup (hello : Text , fab : Circle ) {
632+ fab.onMouseClicked = EventHandler {
633+ println (" Before launch" )
634+ launch(UI ) {
635+ println (" Inside coroutine" )
636+ delay(100 )
637+ println (" After delay" )
638+ }
639+ println (" After launch" )
640+ }
641+ }
642+ ```
643+
644+ > You can get full JavaFx code [ here] ( kotlinx-coroutines-javafx/src/test/kotlin/guide/example-ui-advanced-01.kt ) .
645+
646+ When we start this code and click on a pinkish circle, the following messages are printed to the console:
647+
648+ ``` text
649+ Before launch
650+ After launch
651+ Inside coroutine
652+ After delay
653+ ```
654+
655+ As you can see, execution immediately continues after [ launch] , while the coroutine gets posted onto UI thread
656+ for execution later. All UI dispatchers in ` kotlinx.coroutines ` are implemented this way. Why so?
657+
658+ Basically, the choice here is between "JS-style" asynchronous approach (async actions
659+ are always postponed to be executed later in the even dispatch thread) and "C#-style" approach
660+ (async actions are executed in the invoker thread until the first suspension point).
661+ While, C# approach seems to be more efficient, it ends up with recommendations like
662+ "use ` yield ` if you need to ....". This is error-prone. JS-style approach is more consistent
663+ and does not require programmers to think about whether they need to yield or not.
664+
665+ However, in this particular case when coroutine is started from an event handler and there is no other code around it,
666+ this extra dispatch does indeed add an extra overhead without bringing any additional value.
667+ In this case an optional [ CoroutineStart] parameter to [ launch] , [ async] and [ actor] coroutine builders
668+ can be used for performance optimization.
669+ Setting it to the value of [ CoroutineStart.UNDISPATCHED] has the effect of starting to execute
670+ coroutine immediately until its first suspension point as the following example shows:
671+
672+ ``` kotlin
673+ fun setup (hello : Text , fab : Circle ) {
674+ fab.onMouseClicked = EventHandler {
675+ println (" Before launch" )
676+ launch(UI , CoroutineStart .UNDISPATCHED ) { // <--- Notice this change
677+ println (" Inside coroutine" )
678+ delay(100 ) // <--- And this is where coroutine suspends
679+ println (" After delay" )
680+ }
681+ println (" After launch" )
682+ }
683+ }
684+ ```
685+
686+ > You can get full JavaFx code [ here] ( kotlinx-coroutines-javafx/src/test/kotlin/guide/example-ui-advanced-02.kt ) .
687+
688+ It prints the following messages on click, confirming that code in the coroutine starts to execute immediately:
689+
690+ ``` text
691+ Before launch
692+ Inside coroutine
693+ After launch
694+ After delay
695+ ```
621696
622697<!-- - SITE_ROOT https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core -->
623698<!-- - DOCS_ROOT kotlinx-coroutines-core/target/dokka/kotlinx-coroutines-core -->
@@ -629,6 +704,9 @@ when the parent job is cancelled. An example of that is shown in
629704[ run ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
630705[ CommonPool ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
631706[ NonCancellable ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
707+ [ CoroutineStart ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-start/index.html
708+ [ async ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
709+ [ CoroutineStart.UNDISPATCHED ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-start/-u-n-d-i-s-p-a-t-c-h-e-d.html
632710<!-- - INDEX kotlinx.coroutines.experimental.channels -->
633711[ actor ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
634712[ SendChannel.offer ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/offer.html
0 commit comments