kdnakt blog

hello there.

第57回Kotlin dojoを開催した

今週は第57回を開催しました!

引き続きKotlin Hands-onをすすめています。

 

前回の様子はコチラ↓

kdnakt.hatenablog.com

  

 

[第57回の様子]

2021/3/24に第56回を開催した。

 

参加メンバーは自分をいれて3名。今回は久しぶりのメンバーも参加してくれた!

今回、自分はナビゲータ役で参加した。

 

勉強会本編の内容としては、ひき続きIntroduction to Coroutines and Channelsハンズオンを進めた。第6章 Structured Concurrencyを半分ほど進めた。

 

[学んだことや疑問点]

  • Introduction to Coroutines and Channels: 6. Structured Concurrency
    • Coroutine scopeの役割は異なるCoroutine間の親子関係を持たせること
    • Coroutine contextにはcoroutineの名前やどのスレッドでcoroutineを実行すべきかといった追加の技術情報が含まれている
    • launchasyncによって、新しいcoroutineは常にcoroutine scopeの中でのみ開始できる:runBlockingのみ例外的なトップレベル関数として定義されている
    • launchasyncCoroutineScopeの拡張関数なのでcoroutine scopeの中でのみ呼び出せる
import kotlinx.coroutines.*

fun main() = runBlocking { /* ここでのthisはCoroutineScope */
    launch { /* これはrunBlockingで開始されたCoroutineScopeの子供のスコープ */ } 
    // 上の行は以下の行と同じ意味    
    this.launch { /* ... */ }
}
    • coroutineScope()関数を使うとcoroutineを開始することなくCoroutineScopeを作成できる
    • suspend関数のなかで新しいcoroutineを使う場合にcoroutineScope()関数を利用した(前回・前々回のloadContributorsConcurrent関数がそれ:suspend関数はcoroutine scopeの中で呼ばれるので、そのスコープの子供のスコープが作成される)
    • GlobalScope.async()GlobalScope.launch()で親子関係のない独立したcoroutine scopeを開始することもできる:独立しているので明示的にcoroutineへの参照を保持してキャンセルする必要がある
    • Coroutine Scopeに親子関係があることで以下の利点がある
      • 親スコープが子のスコープを管理する、子の寿命は親の寿命に制限される
      • 親スコープがキャンセルされると、子のcoroutineもキャンセルされる
      • 親coroutineは子のcoroutineの完了を待つ
    • ローディング処理をキャンセルする
    • 前回実装したloadContributorsConcurrentをキャンセルしやすくするために、delay処理を追加する
suspend fun loadContributorsConcurrent(service: GitHubService, req: RequestData): List<User> = coroutineScope {
    // ... 
    async {
        log("starting loading for ${repo.name}")
        delay(3000)
        // load repo contributors
    }
    // ...
    result
}
    • さらにこれをコピーしてloadContributorsNotCancellableを実装する。
    • coroutineScopeの呼び出しをなくすとラムダ式内のthisCoroutineScopeでなくなるため、asyncコンパイルエラーになる
    • これをGlobalScope.asyncに修正してできあがり
suspend fun loadContributorsConcurrent(service: GitHubService, req: RequestData): List<User> = {
    // ... 
    GlobalScope.async {
        log("starting loading for ${repo.name}")
        delay(3000)
        // load repo contributors
    }
    // ...
    result
}
    • 動作確認をするぞ!というところで時間ぎれ....続きは次週!

 

[まとめ]

モブプログラミング・スタイルで、Introduction to Coroutines and Channelsハンズオンを進めた。

Coroutineのcontextとscopeの違い、scopeの親子関係とGlobalScopeなど、Structured Concurrencyについて理解を深められた!!

 

今週のプルリクエストはこちら。

github.com