@@ -104,8 +104,9 @@ context object for your favourite UI library, even if it is not included out of
104
104
* [ Blocking operations] ( #blocking-operations )
105
105
* [ The problem of UI freezes] ( #the-problem-of-ui-freezes )
106
106
* [ 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 )
109
110
110
111
<!-- - END_TOC -->
111
112
@@ -538,11 +539,11 @@ Note, that because the `fib` function is invoked from the single actor in our co
538
539
computation of it at any given time, so this code has a natural limit on the resource utilization.
539
540
It can saturate at most one CPU core.
540
541
541
- ## Lifecycle
542
+ ## Advanced topics
542
543
543
- This section outlines an approach to life-cycle management with coroutines .
544
+ This section covers various advanced topics .
544
545
545
- ### Using coroutine parent-child hierarchy
546
+ ### Lifecycle and coroutine parent-child hierarchy
546
547
547
548
A typical UI application has a number of elements with a lifecycle. Windows, UI controls, activities, views, fragments
548
549
and 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
618
619
the view and in its context can create further children coroutines. The whole tree of coroutines gets cancelled
619
620
when the parent job is cancelled. An example of that is shown in
620
621
[ "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
+ ```
621
696
622
697
<!-- - SITE_ROOT https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core -->
623
698
<!-- - 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
629
704
[ run ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
630
705
[ CommonPool ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
631
706
[ 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
632
710
<!-- - INDEX kotlinx.coroutines.experimental.channels -->
633
711
[ actor ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
634
712
[ SendChannel.offer ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/offer.html
0 commit comments