Droid knights 2019 - Kotlin Corotuines

7589a5a8fec022e8af4e46525150a291?s=47 TaeHwan
April 05, 2019

Droid knights 2019 - Kotlin Corotuines

It deals with Kotlin coroutines.
CoroutineScope, GlobalScope, Android Lifecycle Following, Job, Poor Job, Good Job, supervisorScope, suspendCancellableCoroutine

7589a5a8fec022e8af4e46525150a291?s=128

TaeHwan

April 05, 2019
Tweet

Transcript

  1. ௏ܖ౯উ੹ ੉ࢁѱ௏ܖ౯ࢎਊೞחߑߨ਷ 4QFBLFS 5BFIXBO

  2. • GDG Seoul ਍৔૓ • ٘۽੉٘ ա੉எ ਍৔૓ • ੹)

    ٧ܻߡܻ൤য۽௏ܻই উ٘۽੉٘ ѐߊ • അ) ஠஠য়ಕ੉ উ٘۽੉٘ ѐߊ • Blog : Է ݆਷ ѐߊ੗о غ੗! (https://thdev.tech) ࣗѐ
  3. $PSPVUJOFT

  4. $PSPVUJOFT ↟"TZODISPOPVTPSOPOCMPDLJOHQSPHSBNNJOH ↟$PSPVUJOFTMJHIUXFJHIUUISFBE ↟4VQQPSUTFSWFSTJEF EFTLUPQPSNPCJMFBQQMJDBUJPOT $PSPVUJOFT਷

  5. $PSPVUJOF4DPQF $PSPVUJOFTDPEF @Test fun testCoroutines() = runBlocking { CoroutineScope(Dispatchers.Default) .launch

    { } delay(1500) } println("Hello") delay(1000) println("droid knights!!!")
  6. $PSPVUJOF4DPQF $PSPVUJOFTDPEF @Test fun testCoroutines() = runBlocking { CoroutineScope(Dispatchers.Default) .launch

    { } delay(1500) } Hello println("Hello") delay(1000) println("droid knights!!!") Droid knights!!! delay 1 sec
  7. $PSPVUJOF4DPQF

  8. $PSPVUJOF4DPQF ↟$PSPVUJOFTࢎਊߧਤ੿੄ $PSPVUJOF4DPQF੉ۆ

  9. $PSPVUJOF4DPQF $PSPVUJOF4DPQF੉ۆ ↟$PSPVUJOFTࢎਊߧਤ੿੄ ↟ݽٚ$PSPVUJOFT਷$PSPVUJOF4DPQF࢚ࣘ public interface CoroutineScope { /* *

    Context of this scope. */ public val coroutineContext: CoroutineContext }
  10. $PSPVUJOF4DPQF $PSPVUJOF4DPQF੉ۆ ↟$PSPVUJOFTࢎਊߧਤ੿੄ ↟ݽٚ$PSPVUJOFT਷$PSPVUJOF4DPQF࢚ࣘ ↟ݽٚ$PSPVUJOF਷ة݀੸ੋ+PCਸઁҕ ↟$PSPVUJOFCVJMEFS MBVODI BTZOD١  ↟4DPQJOHGVODUJPO

    DPSPVUJOF4DPQF XJUI$POUFYU١
  11. $PSPVUJOF4DPQF $PSPVUJOF4DPQFز੘ CoroutineScope(Dispatchers.IO).launch { val jobOne = launch { //

    jobOne } val jobTwo = launch { // jobTwo launch(Dispatchers.Main) { // jobTwo UI Thread } } jobOne.join() jobTwo.join() } jobOne jobTwo jobTwo(Main) jobOne / jobTwo زद प೯ Job two উীࢲ UI ୊ܻ CoroutineScope jobOne/jobTwo ઙܐ ؀ӝ
  12. (MPCBM4DPQF

  13. $PSPVUJOF4DPQF (MPCBM4DPQF੉ۆ ↟$PSPVUJOF4DPQFਸ࢚ࣘ߉ח(MPCBM4DPQF ↟(MPCBM4DPQF਷੹৉ীࢲೞա۽ز੘ೠ׮ ↟PCKFDU यӖహਵ۽ز੘  ↟ചݶҗޖҙೞѱࢲ࠺झ੘স೙ਃदࢎਊоמ ↟OFX$PSPVUJOF$POUFYUઁҕਵ۽ਗೞח5ISFBEഋక۽߸҃оמ

  14. $PSPVUJOF4DPQF (MPCBM4DPQF੉ۆ public object GlobalScope : CoroutineScope { /* *

    Returns [EmptyCoroutineContext]. */ override val coroutineContext: CoroutineContext get() = EmptyCoroutineContext } (MPCBM4DPQF੄*0 XPSLFS UISFBEীࢲز੘ 5ISFBE<%FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOF  NBJO>
  15. "OESPJE-JGFDZDMFٮܰӝ

  16. $PSPVUJOF4DPQF "OESPJEMJGFDZDMFٮܰӝ ↟"OESPJEMJGFDZDMFীٮۄPO%FTUPSZ ীࢲ KPCDBODFM ਃ୒ onDestory job.cancel() Activity

  17. $PSPVUJOFT $PSPVUJOFTDPEF class MyActivity : AppCompatActivity(), CoroutineScope { // Jobਸ

    ١۾ೡ ࣻ ੓ب۾ ୡӝച private val job: Job = SupervisorJob() // ӝࠄ Main Thread ੿੄৬ jobਸ ೣԋ ୡӝച override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job // ੘স ઺੉؍ ݽٚ jobਸ ઙ childrenਸ ઙܐ ୊ܻ override fun onDestroy() { super.onDestroy() job.cancel() // Cancel job on activity destroy. // After destroy all children jobs will be cancelled automatically } }
  18. +PC

  19. ↟+PC਷JOUFSGBDF۽੿੄غয੓׮ +PC $PSPVUJOFTKPC public interface Job : CoroutineContext.Element { //

    ... public val isActive: Boolean public val isCompleted: Boolean // ... }
  20. ↟+PC਷JOUFSGBDF۽੿੄غয੓׮ ↟MBVODI١ࢎਊदKPCё୓ܳSFUVSO // return jobਵ۽ ஶ౟܀ೞӝ val job = CoroutineScope(

    Dispatchers.Default).launch { // … } job.join() ↟߹ب੄KPCਸࢤࢿೡࣻ੓׮ val job = Job() CoroutineScope( Dispatchers.Default + job) .launch { } +PC $PSPVUJOFTKPC
  21. +PC ↟+PC਷JOUFSGBDF۽੿੄غয੓׮ ↟MBVODI١ࢎਊदKPCё୓ܳSFUVSO ↟߹ب੄KPCਸࢤࢿೡࣻ੓׮ ↟KPC੉ਊदDPSPVUJOF੄DBODFM TUBSU KPJO١ਸೡࣻ੓׮ $PSPVUJOFTKPC

  22. +PC ↟+PC਷JOUFSGBDF۽੿੄غয੓׮ ↟MBVODI١ࢎਊदKPCё୓ܳSFUVSO ↟߹ب੄KPCਸࢤࢿೡࣻ੓׮ ↟KPC੉ਊदDPSPVUJOF੄DBODFM TUBSU KPJO١ਸೡࣻ੓׮ ↟TUBSUDPSPVUJOFز੘࢚కഛੋ ↟USVFز੘઺ GBMTFળ࠺઺৮ܐ

    $PSPVUJOFTKPC ↟KPJODPSPVUJOF4DPQF੄ز੘ઙܐܳ؀ӝ ↟DBODFMDPSPVUJOF4DPQF੄ز੘ਸઙܐਬب ↟DBODFM"OE+PJODPSPVUJOF4DPQF੄ز੘ઙܐਃ୒ೞҊ ؀ӝ ↟DBODFM$IJMESFODPSPVUJOF4DPQF੄DIJMESFO੄ز੘ਸઙܐਬب
  23. +PC $PSPVUJOFTKPCTUBUVT New Active Start Completing Complete Completed Finish Cancelling

    Cancelled cancel/fail Finish
  24. +PC $PSPVUJOFTKPCTUBUVTଵҊਊद౟ State isActive isCompleted isCancelled New (optional initial state)

    FALSE FALSE FALSE Active (default initial state) TRUE FALSE FALSE Completing (transient state) TRUE FALSE FALSE Cancelling (transient state) FALSE FALSE TRUE Cancelled (final state) FALSE TRUE TRUE Completed (final state) FALSE TRUE FALSE
  25. +PC ੜޅࢎਊೠ৘

  26. ↟$PSPVUJOF4DPQF੿੄ +PC +PCੜޅࢎਊೠ৘ٜܳ݅যࠁ੗ CoroutineScope Default Scope New CoroutineScope loop ↟%FGBVMU4DPQF੿੄

    ↟/FX$PSPVUJOF4DPQF୶о੿੄
  27. @Test fun testCoroutines() = runBlocking { val job = Job()

    CoroutineScope(Dispatchers.Default + job).launch { CoroutineScope(Dispatchers.Default).launch { println("New CoroutineScope for start") for (index in 0..20) { if (isActive) { println("New CoroutineScope index $index") delay(1) } else { break } } println("New CoroutineScope for end") } val defaultJob = launch { println("Default for start") for (index in 0..10) { if (isActive) { println("Default index $index") +PC +PCੜޅࢎਊೠ৘DPEF
  28. @Test fun testCoroutines() = runBlocking { val job = Job()

    CoroutineScope(Dispatchers.Default + job).launch { CoroutineScope(Dispatchers.Default).launch { println("New CoroutineScope for start") for (index in 0..20) { if (isActive) { println("New CoroutineScope index $index") delay(1) } else { break } } println("New CoroutineScope for end") } val defaultJob = launch { println("Default for start") for (index in 0..10) { if (isActive) { println("Default index $index") +PC +PCੜޅࢎਊೠ৘DPEF Main CoroutineScope ୡӝച New CoroutineScope ୡӝച दীח job ನೣೞ૑ ঋ਺
  29. println("New CoroutineScope index $index") delay(1) } else { break }

    } println("New CoroutineScope for end") } val defaultJob = launch { println("Default for start") for (index in 0..10) { if (isActive) { println("Default index $index") delay(1) } else { break } } println("Default for end") } defaultJob.join() } job.cancel() delay(30) // 30ms test only. } +PC +PCੜޅࢎਊೠ৘DPEF Main CoroutinesCope਷ द੘җ زदী cancel ഐ୹ೠ׮
  30. +PC /FX$PSPVUJOF4DPQFGPSTUBSU /FX$PSPVUJOF4DPQFJOEFY %FGBVMUGPSTUBSU %FGBVMUGPSFOE /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFJOEFY j /FX$PSPVUJOF4DPQFJOEFY

    /FX$PSPVUJOF4DPQFGPSFOE +PCੜޅࢎਊೠ৘$PEFѾҗ
  31. +PC /FX$PSPVUJOF4DPQFGPSTUBSU /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFJOEFY j /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFGPSFOE +PCੜޅࢎਊೠ৘$PEFѾҗ

    Default Job਷ द੘ റ ૊द ઙܐغ঻׮ %FGBVMUGPSTUBSU %FGBVMUGPSFOE New CoroutineScope਷ Default Jobҗ ޖҙೞѱ ز੘
  32. +PC +PCੜޅࢎਊೠ৘ޙઁܳ଺ইࠁ੗ ↟$PSPVUJOF4DPQFઙܐ ↟/FX$PSPVUJOF4DPQF҅ࣘ੘স઺ ↟/FX$PSPVUJOF4DPQFਸઁযೡߑߨ੉হ׮ CoroutineScope Default Scope New CoroutineScope

    loop 1. CoroutinScope ઙܐ 2. CoroutineScope ઙܐ೧ب ҅ࣘ ز੘
  33. @Test fun testCoroutines() = runBlocking { val job = Job()

    CoroutineScope(Dispatchers.Default + job).launch { CoroutineScope(Dispatchers.Default + job).launch { println("New CoroutineScope for start") for (index in 0..20) { if (isActive) { println("New CoroutineScope index $index") delay(1) } else { break } } println("New CoroutineScope for end") } val defaultJob = launch { println("Default for start") for (index in 0..10) { if (isActive) { println("Default index $index") delay(1) +PC ೧Ѿ New CoroutineScope ୡӝച दীب jobਸ ୶о
  34. +PC /FX$PSPVUJOF4DPQFGPSTUBSU /FX$PSPVUJOF4DPQFJOEFY %FGBVMUGPSTUBSU %FGBVMUJOEFY /FX$PSPVUJOF4DPQFJOEFY +PC߸҃ী؀ೠѾҗ

  35. +PC /FX$PSPVUJOF4DPQFGPSTUBSU /FX$PSPVUJOF4DPQFJOEFY /FX$PSPVUJOF4DPQFJOEFY +PC߸҃ী؀ೠѾҗ %FGBVMUGPSTUBSU %FGBVMUJOEFY Default scope਷ 0

    ө૑ ୹۱ ೞҊ ઙܐ New CoroutineScope਷ 1 ө૑ ୹۱ ೞҊ ઙܐ
  36. +PC݅ਵ۽ݽٚѦ೧Ѿೡࣻ੓ਸө

  37. +PC +PCਸખ؊࢓ಝࠁ੗ private val job = Job() private val coroutineScope

    = CoroutineScope(Dispatchers.IO + job) @Test fun testException() = runBlocking { with(coroutineScope) { println("Parent scope") val firstChildren = launch { println("First children is failing") throw Exception("First children is exception") } val secondChildren = launch { println("Second children is success") delay(500) println("Second children is delay 500ms") } firstChildren.join() secondChildren.join() } }
  38. +PC +PCਸખ؊࢓ಝࠁ੗ private val job = Job() private val coroutineScope

    = CoroutineScope(Dispatchers.IO + job) @Test fun testException() = runBlocking { with(coroutineScope) { println("Parent scope") val firstChildren = launch { println("First children is failing") } val secondChildren = launch { println("Second children is success") delay(500) println("Second children is delay 500ms") } firstChildren.join() secondChildren.join() } } Exception ъઁ ߊࢤ throw Exception("First children is exception")
  39. +PC 1BSFOUTDPQF 'JSTUDIJMESFOJTGBJMJOH &YDFQUJPOJOUISFBE%FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOF&YDFQUJPOJOUISFBE %FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOFKBWBMBOH&YDFQUJPO'JSTUDIJMEJTFYDFQUJPO  BU UFDIUIEFWDPSPVUJOFTTDPQF6*$PSPVUJOF4DPQF5FTUUFTU&YDFQUJPODIJME+PCJOWPLF 4VTQFOE 6*$PSPVUJOF4DPQF5FTULU

     j KBWBMBOH&YDFQUJPO'JSTUDIJMESFOJTFYDFQUJPO j +PCਸખ؊࢓ಝࠁ੗
  40. +PC 1BSFOUTDPQF 'JSTUDIJMESFOJTGBJMJOH &YDFQUJPOJOUISFBE%FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOF&YDFQUJPOJOUISFBE %FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOFKBWBMBOH&YDFQUJPO'JSTUDIJMEJTFYDFQUJPO  BU UFDIUIEFWDPSPVUJOFTTDPQF6*$PSPVUJOF4DPQF5FTUUFTU&YDFQUJPODIJME+PCJOWPLF 4VTQFOE 6*$PSPVUJOF4DPQF5FTULU

     j KBWBMBOH&YDFQUJPO'JSTUDIJMESFOJTFYDFQUJPO j +PCਸખ؊࢓ಝࠁ੗ Parent scope੉ ઙܐغ঻׮.
  41. ޙࢲܳా೧ޙઁܳ଺ইࠁ੗

  42. +PC 5IFNPTUCBTJDJOTUBODFTPG+PCBSFDSFBUFEXJUIMBVODIDPSPVUJOFCVJMEFSPSXJUIB+PC  GBDUPSZGVODUJPO#ZEFGBVMU BGBJMVSFPGBOZPGUIFKPCsTDIJMESFOMFBETUPBOJNNFEJBUFMZ GBJMVSFPGJUTQBSFOUBOEDBODFMMBUJPOPGUIFSFTUPGJUTDIJMESFO5IJTCFIBWJPSDBOCF DVTUPNJ[FEVTJOH4VQFSWJTPS+PC ޙࢲ۽ഛੋ೧ࠁ੗ #ZEFGBVMU BGBJMVSFPGBOZPGUIFKPCsTDIJMESFOMFBETUPBOJNNFEJBUFMZ

    GBJMVSFPGJUTQBSFOUBOEDBODFMMBUJPOPGUIFSFTUPGJUTDIJMESFO ޙࢲ : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/ +PC ਷DIJMESFO઺ೞաоઙܐغݶ ࠗݽীѱా૑ೞҊ ࠗݽחݽٚDIJMESFOਸઙܐೞҊ ੗ӝب ઙܐೠ׮
  43. +PC ޙࢲܳӝ߈ਵ۽௏٘ܳ׮द࢓ಝࠁ੗ private val job = Job() private val coroutineScope

    = CoroutineScope(Dispatchers.IO + job) @Test fun testException() = runBlocking { with(coroutineScope) { println("Parent scope") val firstChildren = launch { println("First children is failing") throw Exception("First children is exception") } val secondChildren = launch { println("Second children is success") delay(500) println("Second children is delay 500ms") } firstChildren.join() secondChildren.join() } } Parent Scope਷ ׮ܲ childrenਸ ݽف ઙܐೞҊ, ੗ӝب ઙܐೠ׮. Exception ߊࢤ द ࠗݽীѱ ా૑
  44. +PC $PSPVUJOF4DPQ/ѐDIJMESFOਸо૕ࣻ੓׮ ੿ܻೞݶ Main CoroutineScope JobOne JobTwo … JobN 1ѐ੄

    children Exception ߊࢤ ݽٚ childrenҗ ࠗݽ ݽف ઙܐ ೞաۄبલਵݶࠗݽীѱా૑ೞҊݽفઙܐೠ׮
  45. +PC݈Ҍহਸө  ׮दޙࢲܳഛੋ೧ࠁ੗

  46. +PC ׮दޙࢲܳࠁ੗ 5IFNPTUCBTJDJOTUBODFTPG+PCBSFDSFBUFEXJUIMBVODIDPSPVUJOFCVJMEFSPSXJUIB+PC  GBDUPSZGVODUJPO#ZEFGBVMU BGBJMVSFPGBOZPGUIFKPCsTDIJMESFOMFBETUPBOJNNFEJBUFMZ GBJMVSFPGJUTQBSFOUBOEDBODFMMBUJPOPGUIFSFTUPGJUTDIJMESFO ޙࢲ : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/

    5IJTCFIBWJPSDBOCF DVTUPNJ[FEVTJOH4VQFSWJTPS+PC
  47. 4VQFSWJTPS+PC

  48. 4VQFSWJTPS+PC 4VQFSWJTPS+PCޙࢲഛੋ $SFBUFTBOFXTVQFSWJTPSKPCPCKFDUJOBOBDUJWFTUBUF$IJMESFOPGBTVQFSWJTPSKPCDBOGBJM JOEFQFOEFOUMZPGFBDIPUIFS ޙࢲ : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/ $IJMESFOPGBTVQFSWJTPSKPCDBO GBJMJOEFQFOEFOUMZPGFBDIPUIFS $IJMESFO੉ة݀੸ੋFYDFQUJPO੉оמೞ׮

  49. Job() +PC 4VQFSWJTPS+PC੸ਊೞӝ private val job = private val coroutineScope

    = CoroutineScope(Dispatchers.IO + job) @Test fun testException() = runBlocking { with(coroutineScope) { println("Parent scope") val firstChildren = launch { println("First children is failing") throw Exception("First children is exception") } val secondChildren = launch { println("Second children is success") delay(500) println("Second children is delay 500ms") } firstChildren.join() secondChildren.join() } } SupervisorJob() private val coroutineScope = CoroutineScope(Dispatchers.IO + job) @Test fun testException() = runBlocking { with(coroutineScope) { println("Parent scope") val firstChildren = launch { println("First children is failing") throw Exception("First children is exception") } val secondChildren = launch { println("Second children is success") delay(500) println("Second children is delay 500ms") } firstChildren.join() secondChildren.join() } }
  50. 4VQFSWJTPS+PC 4VQFSWJTPS+PC੸ਊѾҗ 1BSFOUKPC 'JSTUDIJMEJTGBJMJOH 4FDPOEDIJMEJTTVDDFTT j &YDFQUJPOJOUISFBE%FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOFKBWBMBOH&YDFQUJPO'JSTU DIJMEJTFYDFQUJPO BU UFDIUIEFWDPSPVUJOFTTDPQF6*$PSPVUJOF4DPQF5FTUUFTU&YDFQUJPODIJME+PCJOWPLF4VTQ

    FOE 6*$PSPVUJOF4DPQF5FTULU j 4FDPOEDIJMEJTEFMBZNT 1BSFOUTDPQF 'JSTUDIJMESFOJTGBJMJOH 4FDPOEDIJMESFOJTTVDDFTT 4FDPOEDIJMESFOJTEFMBZNT
  51. ખ؊ঌইࠁ੗

  52. public fun Job(parent: Job? = null): Job = JobImpl(parent) public

    fun SupervisorJob(parent: Job? = null) : Job = SupervisorJobImpl(parent) +PC +PCҗ4VQFSWJTPS+PCਸୡӝചೞח௏٘
  53. internal class JobImpl(parent: Job? = null) : JobSupport(true) { init

    { initParentJobInternal(parent) } override val cancelsParent: Boolean get() = true override val onCancelComplete get() = true override val handlesException: Boolean get() = false } +PC +PC*NQM4VQFSWJTPS+PC*NQM੄ҳഅ୓ܳࠁ੗ private class SupervisorJobImpl(parent: Job?) : JobSupport(true) { init { initParentJobInternal(parent) } override val cancelsParent: Boolean get() = true override val onCancelComplete get() = true override val handlesException: Boolean get() = false } override fun childCancelled(cause: Throwable): Boolean = false Child ஂࣗ ੿ࠁܳ parentীѱ ੹࣠ೡ૑ ৈࠗܳ Ѿ੿
  54. private fun cancelParent(cause: Throwable): Boolean { if (cause is CancellationException)

    return true if (!cancelsParent) return false return parentHandle?.childCancelled(cause) == true } +PC DIJME$BODFMMFEחয٣ࢲࠗܳө ৈӝীࢲ Ѿ੿ೞৈ ୊ܻೠ׮
  55. &YDFQUJPO੉߮౟୊ܻ

  56. &YDFQUJPO੉߮౟୊ܻ য়ܨ௏٘׮दഛੋ j &YDFQUJPOJOUISFBE%FGBVMU%JTQBUDIFSXPSLFS!DPSPVUJOFKBWBMBOH&YDFQUJPO'JSTU DIJMEJTFYDFQUJPO BU UFDIUIEFWDPSPVUJOFTTDPQF6*$PSPVUJOF4DPQF5FTUUFTU&YDFQUJPODIJME+PCJOWPLF4VTQ FOE 6*$PSPVUJOF4DPQF5FTULU j

    1BSFOUTDPQF 'JSTUDIJMESFOJTGBJMJOH 4FDPOEDIJMESFOJTTVDDFTT 4FDPOEDIJMESFOJTEFMBZNT
  57. &YDFQUJPO੉߮౟୊ܻ য়ܨܳ߹ب۽୊ܻ೧ࠁ੗ &YDFQUJPOਸೠߣী୊ܻೡ೙ਃо੓׮ $PSPVUJOFTীࢲ$PSPVUJOF&YDFQUJPO)BOEMFSܳઁҕ ޙࢲIUUQTLPUMJOHJUIVCJPLPUMJOYDPSPVUJOFTLPUMJOYDPSPVUJOFTDPSF LPUMJOYDPSPVUJOFTDPSPVUJOFFYDFQUJPOIBOEMFS

  58. val errorHandler = CoroutineExceptionHandler { coroutineContext, exception -> 
 }

    &YDFQUJPO੉߮౟୊ܻ $PSPVUJOF&YDFQUJPO)BOEMFSࢎਊೞӝ // log to Crashlytics, logcat, etc.; can be dependency injected when (exception) { is NetworkErrorException -> { } is NetworkOnMainThreadException -> { } is CustomException -> { } else -> throw exception
 } ੿੄ೞ૑ ঋ਷ exception਷ Ӓ؀۽ ࠁղ੗
  59. val errorHandler = CoroutineExceptionHandler { coroutineContext, exception -> // log

    to Crashlytics, logcat, etc.; can be dependency injected } &YDFQUJPO੉߮౟୊ܻ $PSPVUJOF&YDFQUJPO)BOEMFSࢎਊೞӝ private val job = SupervisorJob() private val coroutineScope = CoroutineScope(job + Dispatchers.Default + errorHandler) launch(errorHandler)
  60. &YDFQUJPO੉߮౟୊ܻ য়ܨܳ߹ب۽୊ܻ೧ࠁ੗ 1BSFOUTDPQF 'JSTUDIJMESFOJTGBJMJOH 4FDPOEDIJMESFOJTTVDDFTT 4FDPOEDIJMESFOJTEFMBZNT KBWBMBOH&YDFQUJPO'JSTUDIJMESFOJTFYDFQUJPO

  61. ژ׮ܲয়ܨ୊ܻ

  62. public suspend fun supervisorScope(block: suspend CoroutineScope.() -> ): = block:

    suspend CoroutineScope.() -> ژ׮ܲয়ܨ୊ܻ TVQFSWJTPS4DPQF suspendCoroutineUninterceptedOrReturn { uCont -> val coroutine = SupervisorCoroutine(uCont.context, uCont) coroutine.startUndispatchedOrReturn(coroutine, block) } <R> R R
  63. @Test fun testException() = runBlocking { with(coroutineScope) println("Parent scope") val

    firstChildren = launch { println("First children is failing") throw Exception("First children is exception") } val secondChildren = launch { println("Second children is success") delay(500) println("Second children is delay 500ms") } firstChildren.join() secondChildren.join() } } with(coroutineScope) { ژ׮ܲয়ܨ୊ܻ TVQFSWJTPS4DPQFࢎਊ਷ supervisorScope {
  64. ژ׮ܲয়ܨ୊ܻ TVQFSWJTPS4DPQFࢎਊ਷ 1BSFOUTDPQF 'JSTUDIJMESFOJTGBJMJOH j 4FDPOEDIJMESFOJTTVDDFTT j   

     4FDPOEDIJMESFOJTEFMBZNT  BUPSHKVOJUSVOOFST#MPDL+6OJU$MBTT3VOOFSSVO$IJME #MPDL+6OJU$MBTT3VOOFSKBWB   BUDPNJOUFMMJKSUFYFDVUJPOKVOJU+6OJU4UBSUFSNBJO +6OJU4UBSUFSKBWB &YDFQUJPOJOUISFBENBJO!DPSPVUJOFKBWBMBOH&YDFQUJPO'JSTUDIJMESFOJTFYDFQUJPOBU UFDIUIEFWDPSPVUJOFTTDPQF6*$PSPVUJOF4DPQF5FTUUFTU&YDFQUJPOGJSTU$IJMESFOJOWPLF4VTQF OE 6*$PSPVUJOF4DPQF5FTULU
  65. private class SupervisorCoroutine<R>( parentContext: CoroutineContext, @JvmField val uCont: Continuation<R> )

    : AbstractCoroutine<R>(parentContext, true) { override val defaultResumeMode: Int get() = MODE_DIRECT @Suppress("UNCHECKED_CAST") internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { if (state is CompletedExceptionally) uCont.resumeUninterceptedWithExceptionMode(state.cause, mode) else uCont.resumeUninterceptedMode(state as R, mode) } } ژ׮ܲয়ܨ୊ܻ TVQFSWJTPS4DPQF੄DIJME$BODFMMFE୊ܻ override fun childCancelled(cause: Throwable): Boolean = false
  66. ೞա؊ TVTQFOE$BODFMMBCMF$PSPVUJOF

  67. ೞա؊ 4VTQFOETDPSPVUJOFTJNJMBSUPTVTQFOE$PSPVUJOF CVUQSPWJEFBOJNQMFNFOUBUJPOPG $BODFMMBCMF$POUJOVBUJPOUPUIFCMPDL5IJTGVODUJPOUISPXT$BODFMMBUJPO&YDFQUJPOJGUIF DPSPVUJOFJTDBODFMMFEPSDPNQMFUFEXIJMFTVTQFOEFE TVTQFOE$BODFMMBCMF$PSPVUJOF ޙࢲ : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/suspend-cancellable-coroutine.html TVTQFOE$PSPVUJOFҗਬࢎ

    $PSPVUJOFੌद઺૑ژחஂࣗद$BODFMMBUJPO&YDFQUJPOਸੌਵఅ׮ TJNJMBSUPTVTQFOE$PSPVUJOF $BODFMMBUJPO&YDFQUJPOJGUIF DPSPVUJOFJTDBODFMMFEPSDPNQMFUFEXIJMFTVTQFOEFE
  68. public suspend fun <T : Any> Call<T>.await(): T { return

    enqueue(object : Callback<T> { override fun onResponse(call: Call<T>?, response: Response<T?>) { if (response.isSuccessful) { response.body() ?: throw NullPointerException("Response body is null: $response") } else { throw HttpException(response) } }) } override fun onFailure(call: Call<T>, t: Throwable) { if (continuation.isCancelled) return } }) } } ೞա؊ 3FUSPGJUTVTQFOE$BODFMMBCMF$PSPVUJOF 3FUSPGJUIUUQTLPUMJOHJUIVCJPLPUMJOYDPSPVUJOFTLPUMJOYDPSPVUJOFTDPSFLPUMJOYDPSPVUJOFTDPSPVUJOFFYDFQUJPOIBOEMFS suspendCancellableCoroutine { continuation -> continuation.resumeWith(runCatching { continuation.resumeWithException(t) registerOnCompletion(continuation)
  69. private fun Call<*>.registerOnCompletion(continuation: CancellableContinuation<*>) { continuation.invokeOnCancellation { try { cancel()

    } catch (ex: Throwable) { //Ignore cancel exception } } } ೞա؊ 3FUSPGJUTVTQFOE$BODFMMBCMF$PSPVUJOF 3FUSPGJUIUUQTLPUMJOHJUIVCJPLPUMJOYDPSPVUJOFTLPUMJOYDPSPVUJOFTDPSFLPUMJOYDPSPVUJOFTDPSPVUJOFFYDFQUJPOIBOEMFS
  70. ೞա؊ TVTQFOE$BODFMMBCMF$PSPVUJOF Youtube : https://youtu.be/EOjq4OIWKqM?t=1780

  71. хࢎ೤פ׮ 4QFBLFS 5BFIXBO &NBJMUBFIXBO!UIEFWOFU #MPHUIEFWUFDI

  72. ஠஠য়ಕ੉ ௿ۄ੉঱౟(Android) ѐߊ੗ ৔ੑ ૣ਷ दр ੉ܘ ࢿҗࠁ׮ ؊ ষ୒աҊ

    ֥ۄ਍ ࣁ࢚ਸ ஠஠য়ಕ੉৬ ೣԋ ৌযт, ߄۽ ׼नਸ ӝ׮݀פ׮! ૑ਗೞӝ ◆ ૑ਗ੗Ѻ - ׮নೠ UI ѐߊ ҃೷җ ࢎਊ੗ ҃೷ী ؀ೠ Ө਷ ੉೧ - য়೑ࣗझী Ѣࠗх੉ হҊ ੉೧بо ֫਷ ࠙ - ֤ܻ੸੉Ҋ ୓҅੸ੋ ޙઁ೧Ѿ מ۱ - ബҗ੸ੋ ੄ࢎ੹׳, ࢚؀ߑਸ ҃୒ೞח ழޭפா੉࣌ מ۱