Kotlin Coroutines ことはじめ

0886c70b5ecf3b0b0ee6500c5e47884d?s=47 M.Inomata
November 30, 2019

Kotlin Coroutines ことはじめ

Kotlin Coroutines の基本や仕組みの話です。
Android での話を中心にしてますが、Kotlinが動く環境ならほぼ同じなので、Android以外のKotlin開発者の方も参考になるかと思います。

2019/11/30 Android 研究&発表会登壇資料
https://arap.connpass.com/event/153097/ #arap_osaka

0886c70b5ecf3b0b0ee6500c5e47884d?s=128

M.Inomata

November 30, 2019
Tweet

Transcript

  1. Kotlin Coroutines ͜ͱ͸͡Ί

  2. ࣗݾ঺հ • w ழມॆԝ ͍ͷ·ͨΈͭͻΖ  w ᷂UFDIWFJO୅දɻ
 J04"OESPJEεϚϗΞϓϦΤϯδχΞɻ
 3Y͕޷͖Ͱ͢ɻ

    w QSJWBUFUXJUUFS!JOP
  3. ࠓ೔ͷ࿩ • Kotlinίϧʔνϯͷجຊͱ࢓૊ΈΛ஌Ζ͏

  4. ҰൠతʹɺCoroutine ͱ͸ • தஅɾ࠶։͕Մೳͳαϒϧʔνϯ • ฒߦੑ(Concurrent)Λఏڙ͢Δ

  5. αϒϧʔνϯʹී௨ͷؔ਺(ͳͲ) αϒϧʔνϯ ؔ਺ͳͲ ॲཧ ॲཧ ॲཧ ʜ SFUVSOl)FMMP 8PSMEl ϝΠϯॲཧ

    αϒϧʔνϯ։࢝ ʜ αϒϧʔνϯऴྃ
  6. ίϧʔνϯʹதஅՄೳͳαϒϧʔνϯ ίϧʔνϯ ॲཧ ZJFMElIFMMPz ॲཧ ZJFMElXPSMEz ॲཧ ʜ ϝΠϯॲཧ ίϧʔνϯ։࢝

    ʜ ίϧʔνϯऴྃ
  7. ίϧʔνϯ͸ ฒߦ(Concurrent)ʹಈ࡞͢Δ εϨου" ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ εϨου# ίϧʔνϯ ίϧʔνϯ

    ίϧʔνϯ ίϧʔνϯ
  8. ฒߦ(Concurrent) ͱ ฒྻ(Parallel) • ฒߦ(Concurrent) ͷྫ: Coroutine • ฒྻ(Parallel) ͷྫ:

    ϚϧνεϨουɾϚϧνϓ ϩηε
  9. ฒߦ(Concurrent) != ฒྻ(Parallel) εϨου" ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ͜Ε͸ฒߦͰ͋ͬͯ
 ฒྻͰ͸ͳ͍

    ͜Ε͸ฒߦͰ΋
 ฒྻͰ΋͋Δ εϨου# εϨου" ίϧʔνϯ ίϧʔνϯ
  10. Coroutines 
 are 
 light-weight.

  11. Kotlin Coroutines

  12. Kotlin Coroutine ͷΩϞ • Suspending Function • Structured concurrency •

    CoroutineContext • Async as Sync
  13. Kotlin CoroutineͷΩϞᶃ
 Suspending Function

  14. Suspending Function • Kotlin Coroutines ͸ɺίϧʔνϯͷதஅͰ͖ Δੑ࣭Λ suspend ؔ਺(Suspending Function)Ͱ࣮ݱ͍ͯ͠Δɻ

  15. Suspending Function ͷੑ࣭ • suspend ؔ਺͸ଞͷ suspend ؔ਺ͷதͰ͔͠ ࣮ߦͰ͖ͳ͍ɻ •

    ࢠͷ suspend ؔ਺͕தஅ͢Δͱɺ਌ͷ suspend ؔ਺΋ࢭ·Δɻ • suspend ؔ਺ͷதͰී௨ͷؔ਺(suspendͰͳ ͍ؔ਺)ΛݺͿ͜ͱ͸Ͱ͖Δɻ
  16. Hello world to Kotlin Coroutine

  17. ͜ͷαϯϓϧͰ࢖͍ͬͯΔؔ਺ • ίϧʔνϯϏϧμʔ(ੜ੒ؔ਺): • runBlocking<T> { ... } • CoroutineScope#launch

    { ... } • suspendؔ਺:
 delay(timeMillis: Long) ※஫: runBlocking͸ཚ༻NGɻ
 ɹɹAndroid؀ڥͰ͸࢖Θͳ͍͜ͱʂ
  18. Android ൛

  19. CoroutineScopeΫϥε • ίϧʔνϯͷੜଘظؒΛ؅ཧ͢ΔΦϒδΣΫτɻ • MainScope ... UIεϨουͰಈ࡞͢Δείʔϓɻ 
 → AndroidͷActivity

    ͳͲͱඥ෇͚ͯը໘ͷ
 ɹϥΠϑαΠΫϧͱҰகͤ͞ΒΕΔɻ • GlobalScope ... ΞϓϦͷੜଘظؒͱಉ͡είʔϓɻ
 → όονॲཧͳͲɺΞϓϦੜଘதʹऴΘͬͯ͸ࠔΔॲཧΛ࣮ߦ͢Δɻ
  20. αεϖϯυؔ਺ͷྫ • delay (timeMillis: Long) 
 ... ࢦఆϛϦඵ଴ͭɻ • withTimeout<T>(timeMillis:

    Long) { ... } withTimeoutOrNull<T>(timeMillis: Long) { ...}
 ... ϒϩοΫ಺ͷॲཧ͕ࢦఆϛϦඵΛ௒͑ͨͱ͖ʹ
 ɹλΠϜΞ΢τͤ͞Δɻ • yield() 
 ... ॲཧΛॠஅͯ͠ɺ(͋Ε͹)ଞͷίϧʔνϯʹॲཧΛճ͢ɻ
  21. suspend ͸ϊϯϒϩοΩϯά • suspend = தஅ • ͚ͩͲɺεϨουΛϒϩοΫ͠ͳ͍ • →εϨουΛϒϩοΫ͢Δྫ:

    Thread.sleep()
  22. Coroutine ͷ suspend ؔ਺͸ॲཧΛதஅͯ͠ɺ ଞͷฒߦॲཧதͷίϧʔνϯʹεϨουΛৡΔɻ εϨου" ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ

    ZJFME
  23. εϨου" ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ZJFME

  24. εϨου" ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ZJFME ZJFME ZJFME

  25. Suspend Function Ͱ ίϧʔνϯͷதஅͰ͖Δੑ࣭Λ ࣮ݱ͍ͯ͠Δ

  26. Kotlin CoroutineͷΩϞᶄ
 Structured Concurrency

  27. Structured concurrency ฒߦੑͷߏ଄Խ • ίϧʔνϯ͸਌ࢠؔ܎Λ࣋ͯΔɻ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ

  28. Α͋͘ΔϚϧνεϨουͳ
 ඇಉظॲཧͷ໰୊ • Ұ෦ͷεϨουΛམͱͨ͠(མͪͨ)ͱ͖ʹɺ
 ࢒ΓͷεϨουΛڠௐͤ͞Δͷ͕େมɻ • λΠϛϯά໰୊ͰσουϩοΫͨ͠Γɺҙਤ͠ͳ ͍ڍಈ͕ى͜Γ΍͍͢ɻ • ໰୊͕ى͖ͨͱ͖ʹݪҼڀ໌ɾσόοά͕೉͠

    ͍ɻ
  29. ਌ࢠؔ܎ͷ͋Δίϧʔνϯ͸
 ڠௐͤ͞΍͍͢

  30. ਌ࢠؔ܎ͷ͋Δίϧʔνϯ͸
 ڠௐͤ͞΍͍͢ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ΞΫςΟϒͳ ίϧʔνϯ

  31. ਌͸ࢠڙͷऴྃΛ଴ͬͯऴྃ͢Δ ΞΫςΟϒͳ ίϧʔνϯ ଴ػதͷ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ

    ίϧʔνϯ
  32. ਌ࢠؔ܎ͷ͋Δίϧʔνϯ͸
 ྫ֎ɾΩϟϯηϧ࣌΋ڠௐͤ͞΍͍͢

  33. ਌ࢠؔ܎ͷ͋Δίϧʔνϯ͸
 ྫ֎ɾΩϟϯηϧ࣌΋ڠௐͤ͞΍͍͢ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ྫ֎ൃੜʂ

  34. ਌ίϧʔνϯʹྫ֎Λ఻೻ͯ͠
 ίϧʔνϯΛऴྃ͢Δ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ྫ֎ൃੜʂ ྫ֎εϩʔ ྫ֎εϩʔ

  35. ਌ίϧʔνϯ͕ऴྃ͢Δ࣌͸ɺ
 ࢠίϧʔνϯ΋Ωϟϯηϧ͢Δ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ ྫ֎ൃੜʂ KPCDBODFM KPCDBODFM

  36. ʹ਌ίϧʔνϯΛࢭΊΕ͹ɺ ࢠίϧʔνϯ΋ࢭ·Δ

  37. ਌ࢠϧʔνϯͷείʔϓΛ Ωϟϯηϧ͢Ε͹ɺ ਌ࢠͱ΋Ͳ΋ࢭΊΒΕΔ

  38. ίϧʔνϯͷ࣮ߦείʔϓΛ
 Ωϟϯηϧ͢Δ͚ͩͰશ෦ࢭΊΒΕΔ ίϧʔνϯ .BJO4DPQF KPCDBODFM "DUJWJUZ PO%FTUSPZ TDPQFDBODFM ίϧʔνϯ KPCDBODFM

  39. (࠶ܝ) Android Hello world

  40. ίϧʔνϯ͸Ͳ͏΍ͬͯ ਌ࢠؔ܎Λ࡞͍ͬͯΔͷ͔ʁ → CoroutineScope

  41. launch ͷϥϜμࣜ͸
 this = CoroutineScope

  42. ίϧʔνϯ .BJO4DPQF KPCDBODFM "DUJWJUZ PO%FTUSPZ TDPQFDBODFM ίϧʔνϯ ίϧʔνϯ KPCDBODFM (MPCBM4DPQF

    GlobalScopeͷίϧʔνϯ͸.BJO4DPQFͱؔ܎ͳ͘ಈ͘ʂ launch launch launch
  43. Structured Concurrency Λ ׆༻͢Ε͹ ίϧʔνϯ؅ཧָ͕ʹͳΔ

  44. Kotlin CoroutineͷΩϞᶅ
 CoroutineContext

  45. CoroutineContext %JTQBUDIFSɿ.BJO +PCɿͳ͠ ϝΠϯείʔϓͷίϯςΩετ %JTQBUDIFSɿ.BJO +PCɿίϧʔνϯ είʔϓ1ͷίϯςΩετ %JTQBUDIFSɿ.BJO +PCɿίϧʔνϯ είʔϓͷίϯςΩετ

    %JTQBUDIFSɿ%FGBVMU +PCɿίϧʔνϯ είʔϓͷίϯςΩετ ϝΠϯείʔϓ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ1ͷείʔϓ είʔϓ ίϧʔνϯͷείʔϓ είʔϓ ίϧʔνϯ ίϧʔνϯͷείʔϓ είʔϓ
  46. CoroutineContextͷྫ: Job
 ͋Δίϧʔνϯͷ࣮ߦΛද͢Πϯελϯε • ίϧʔνϯΛ࣮ߦ͢ΔͱJobΛ͔͑͢ɻ

  47. CoroutineContext %JTQBUDIFSɿ.BJO +PCɿͳ͠ ϝΠϯείʔϓͷίϯςΩετ %JTQBUDIFSɿ.BJO +PCɿίϧʔνϯ είʔϓ1ͷίϯςΩετ %JTQBUDIFSɿ.BJO +PCɿίϧʔνϯ είʔϓͷίϯςΩετ

    %JTQBUDIFSɿ%FGBVMU +PCɿίϧʔνϯ είʔϓͷίϯςΩετ ϝΠϯείʔϓ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ1ͷείʔϓ είʔϓ ίϧʔνϯͷείʔϓ είʔϓ ίϧʔνϯ ίϧʔνϯͷείʔϓ είʔϓ
  48. CoroutineContextͷྫ: CorouttineDispatcher
 ίϧʔνϯΛͲͷεϨουͰಈ͔͔͢ΛܾΊΔਓ • Dispatches.Main • Dispatchers.Default • Dispatchers.IO •

    Dispatchers.Unconfined • ͦͷଞ: newSingleThreadContext("threadName") ͳͲ
  49. CoroutineContext %JTQBUDIFSɿ.BJO +PCɿͳ͠ ϝΠϯείʔϓͷίϯςΩετ %JTQBUDIFSɿ.BJO +PCɿίϧʔνϯ είʔϓ1ͷίϯςΩετ %JTQBUDIFSɿ.BJO +PCɿίϧʔνϯ είʔϓͷίϯςΩετ

    %JTQBUDIFSɿ%FGBVMU +PCɿίϧʔνϯ είʔϓͷίϯςΩετ ϝΠϯείʔϓ ίϧʔνϯ ίϧʔνϯ ίϧʔνϯ1ͷείʔϓ είʔϓ ίϧʔνϯͷείʔϓ είʔϓ ίϧʔνϯ ίϧʔνϯͷείʔϓ είʔϓ
  50. CoroutinenContextͷྫ:ͦͷଞ • CoroutineName("name") • NonCancellable • CoroutineExceptionHandler {}

  51. CoroutineContextͷ࢖͍ํ • ίϧʔνϯϏϧμʔͷҾ਺ʹࢦఆͯ͠࢖͏ • + Ͱ࿈݁ʢॏෳͨ͠ઃఆ͸ӈล༏ઌʣͯ͠૊Έ߹ Θͤͯ࡞Δ

  52. CoroutineContextͷ࢖͍ํ • ಉظతʹৼΔ෣ͬͯ͘ΕΔ withContext ͕ศར

  53. Kotlin CoroutineͷΩϞᶅ
 Async as Sync

  54. TwitterΫϥΠΞϯτతͳ ΞϓϦ࣮૷ΛίϧʔνϯͰߟ͑Δɻ ϩάΠϯ 0, λΠϜϥΠϯऔಘ < l͓͸Α͏z lࠓ೔͸ษڧձͰ͢z >

  55. ίϧʔνϯ͸ඇಉظ • ྫ: ϩάΠϯͯ͠λΠϜϥΠϯऔಘ͢ΔAPI࣮૷

  56. ίϧʔνϯ͸ඇಉظʁ • ඇಉظॲཧΛಉظతͳײ֮Ͱखଓ͖తʹॻ͚Δ

  57. ίϧʔνϯ͸ඇಉظॲཧΛಉظ తʢखଓ͖తʣʹॻ͚Δ • ಉظతʹॻ͚ΔͷͰɺ௚ײతͰɺόάΛຒΊࠐΈ ʹ͍͘ɻ(σουϩοΫɾ࣮ߦλΠϛϯά໰୊) • ͳΜͱ͔Listener΍ίʔϧόοΫ஍ࠈ͔Βͷղ์ɻ

  58. async / await ΋͋Δ • async ίϧʔνϯͰɺඇಉظίϧʔνϯʹͭͭ͠ɺ ݁ՌΛ଴ͭ͜ͱ΋Ͱ͖Δ • async

    = ݁ՌΛड͚औΕΔػೳΛ΋ͭ launchɻ
  59. Kotlin ίϧʔνϯͷ جຊ͸͜Ε͚ͩ

  60. Kotlin Coroutineͷ ศརͳػೳͷ঺հ

  61. flow ίϧʔνϯ • flow = γʔέϯεͰॱ࣍݁ՌΛྲྀ͢ async. • Rx ObservableΛࢀߟʹ࡞ΒΕ͍ͯΔɻ

    • map(transform{}), flatMap,ϑΟϧλ,
 ྫ֎෮ؼॲཧ(catch{}), εϨου੾Γସ͑, combineLatest, zip ͳͲ΋͋Δɻ
  62. Channels, produce, actor • Channel<T> ͸ίϧʔνϯؒͷ૒ํ޲ͷσʔ λ΍ΓऔΓʹ͔ͭ͑ΔΦϒδΣΫτɻ • produce<T> {

    } ... ࢠ͕ૹ৴ͯ͠਌͕ड৴͢Δ Ұํ޲νϟϯωϧΛ࡞Δίϧʔνϯɻ • actor<T> { } ... ਌͕ૹ৴ͯ͠ࢠ͕ड৴͢ΔҰํ ޲νϟωϧΛ࡞Δίϧʔνϯɻ
  63. AndroidXͰ࢖͑Δศརͳػೳ • ViewModelScope • LifecycleScope • liveData<T> { LiveDataScope<T> ->

    Unit ... }: LiveData<T>