Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AndroidでKotlin Coroutineを使うときの注意点 | CA BASE NEXT

AndroidでKotlin Coroutineを使うときの注意点 | CA BASE NEXT

Androidアプリ開発において、非同期処理は欠かせないテクニックです。画面の描画を妨げることなく、ネットワークリソースにアクセスしたり、データベースにリクエストする必要があります。また、計算量の多い処理は別スレッドで実行することで、パフォーマンスを改善することができるでしょう。
Kotlin Coroutinesはそれらを強力に支援してくれます。最近ではRetrofitやRoom、DataStoreを始めとした周辺ライブラリもCoroutinesをサポートし、ますます使いやすさが増しています。
一方で、Coroutinesを利用する上で、保守性やテスト容易性の面で、いくつか注意する点があります。また、Lifecycleやエラーハンドリングなどでは、間違えやすいポイントも存在します。
このLTでは、すでにKotlin Coroutinesを使ってAndroidアプリを開発している方に向け、Coroutinesを使う際の注意点を解説します。ぜひ今後の参考にしてもらえると幸いです。

https://ca-base-next.cyberagent.co.jp/sessions/android-kotlin-coroutines

Mori Atsushi

May 27, 2021
Tweet

More Decks by Mori Atsushi

Other Decks in Programming

Transcript

  1. Mori Atsushi
    2019年度 新卒⼊社
    株式会社CyberZ OPENREC.tv
    CyberZ CTO室 メンバー
    次世代マネジメント室 メンバー
    未踏スーパークリエータ
    @at_sushi_at
    @Mori-Atsushi

    View full-size slide

  2. https://note.com/cyberz_cto/n/n f d c

    View full-size slide

  3. https://zenn.dev/at_sushi_at/books/edf adfc

    View full-size slide

  4. • Kotlinの公式ライブラリ
    • ⾮同期処理を強⼒に⽀援、まるで同期処理のように書ける
    Kotlin Coroutines
    Kotlin Coroutines Features/Promises/Rx

    View full-size slide

  5. • Googleも推奨するソリューション
    • AndroidのLifecycleに沿ったキャンセルを実現可能
    • 周辺ライブラリもCoroutinesをサポート
    Retrofit, grpc-kotlin, Room, DataStore, Paging , Store , Jetpack Compose
    Android 🤝 Kotlin Coroutines
    • Lifecycle, Dispatchers, CoroutineContext,
    エラーハンドリング, キャンセル処理, バッファ
    注意する点は多い

    View full-size slide

  6. 🚀 今回のゴール
    既にKotlin Coroutinesを使って
    Androidアプリを開発している⽅に向け、
    キャンセルについてより詳しく知ってもらう。
    • より安全に
    • より効率的に
    • より保守しやすいよう

    View full-size slide

  7. ໨࣍ Contents ໨࣍ Contents ໨࣍ Contents ໨࣍ Contents ໨࣍ Contents
    . Kotlin Coroutinesのキャンセルを扱う
    2. 正しくキャンセルする
    3. 正しくキャンセルさせない

    View full-size slide

  8. . Kotlin Coroutinesのキャンセルを扱う

    View full-size slide

  9. • モバイルデバイスという限られたリソースで、
    正しく処理を中断することは重要
    • 例えば
    フォアグラウンドのときのみUIを更新する
    現在の画⾯を閉じたらリクエスト中のAPIを終了する
    キャンセル
    https://developer.android.com/topic/libraries/architecture/viewmodel

    View full-size slide

  10. • CoroutinesScopeやJobは
    キャンセル可能
    • delay等のsuspend functionが
    CancellationExceptionを
    throwしている
    Coroutinesのキャンセルの仕組み
    CancellationExceptionをthrow
    キャンセル時のハンドリング
    キャンセル時もそうでないときも
    実⾏される

    View full-size slide

  11. • LifecycleOwner.lifecycleScope
    Lifecycleが破棄されたとき(onDestory)に⾃動的にキャンセルされる
    • ViewModel.viewModelScope
    ViewModelの消去時 (onCleared) に⾃動的にキャンセルされる
    AndroidとCoroutinesのキャンセル

    View full-size slide

  12. 2. 正しくキャンセルする

    View full-size slide

  13. 問題:以下のコードはどのように実⾏されるか?
    1,000,000までインクリメント
    500,000のタイミングでキャンセル

    View full-size slide

  14. 正解:1,000,000までインクリメントされる
    1,000,000までインクリメント
    500,000のタイミングでキャンセル
    実⾏結果

    View full-size slide

  15. なぜ?
    • Coroutinesは常にキャンセルされたかどうかを
    知っているわけではない
    • delay等の⼀部のsuspend functionのみ
    キャンセルされたかどうか確認している
    • キャンセルされているか確認するタイミングが
    なければ、最後まで実⾏される

    View full-size slide

  16. • ensureActiveでキャンセルされてないか確認する
    注意点①:キャンセルに対して協⼒的である必要がある
    500,000のタイミングでキャンセル
    1,000,000までインクリメント
    実⾏結果
    キャンセルされていれば
    CancellationExceptionをthrow

    View full-size slide

  17. どのようなコードで考慮すべきか?
    • 通常の処理で問題になることは少ない
    あちこちにキャンセルチェックがあると、
    本質と異なる情報が混じり可読性が落ちる
    • 例えば:
    バックグランドスレッドで重たいアルゴリズムを動作させている場合
    ディスクから複数のファイルを読み込む場合

    View full-size slide

  18. 注意点②:suspendCancellableCoroutineを使う
    • callback処理をsuspend function
    に変更するsuspendCoroutineは
    キャンセルに対応していない
    • 可能な限り
    suspendCancellableCoroutine
    を使う
    キャンセル時の処理

    View full-size slide

  19. 注意点③: CancellationExceptionをcatchしない
    • キャンセル時にthrowされる
    CancellationExceptionも
    catchしてしまうと
    キャンセルされない
    キャンセルされてもリトライしてしまう
    キャンセル時に
    CancellationExceptionをthrowする
    エラーになった際にretryする関数

    View full-size slide

  20. 解決策
    • 特定のエラーだけ
    try-catchする
    • CancellationExceptionを
    再throwする
    エラーになった際にretryする関数
    キャンセル時に
    CancellationExceptionをthrowする
    キャンセルを呼び出し元に
    伝播させる

    View full-size slide

  21. 3. 正しくキャンセルさせない

    View full-size slide

  22. • 画⾯を閉じた際等にキャンセルさせたくない
    処理も存在する
    • 例えば
    購⼊完了後のレシート処理
    ログ送信処理
    キャンセルさせたくない処理
    ViewModel破棄後も続⾏させたい

    View full-size slide

  23. 良くない⽅法:GlobalScopeを使う
    • アプリケーション期間のCoroutineScope (@DelicateCoroutinesApi)
    • contextが不明瞭
    Dispatcherは?
    JobかSupervisorJobか?
    エラーハンドリングは?
    • テストでも
    キャンセルができない
    ViewModel破棄後も続⾏される
    GlobalScopeでlaunch

    View full-size slide

  24. 注意が必要:NonCancellableを利⽤する
    • キャンセルできないJob
    • 記述はシンプルでわかりやすい
    • 個別のキャンセルも
    できなくなり、
    制御が不可能
    • テストでも
    キャンセルができない
    • クリーンアップ等では便利
    ViewModel破棄後も続⾏される
    withContextで指定

    View full-size slide

  25. 個別のキャンセルも出来ない
    • withContext(NonCancellable)
    はいかなる⽅法でも
    キャンセルできない
    • 将来的に予期せぬ不具合を
    引き起こす可能性がある
    jobをcancelしてもapi.purchaseは続⾏される

    View full-size slide

  26. おすすめ:アプリケーション範囲のCoroutineScopeをDIする
    • CoroutineScopeを⾃作
    • テストで制御可能
    • 共通のcontextが利⽤可能
    • 個別の制御も可能
    ViewModel破棄後も続⾏される
    appScopeでlaunch
    エラーハンドラー
    JobやDispatcher
    appScopeを定義

    View full-size slide

  27. まとめ
    • キャンセルを意識することでリソースを効率的に扱うことが出来る
    • 正しくキャンセルさせる
    キャンセルに対して協⼒的である必要がある
    suspendCancellableCoroutineを使う
    CancellationExceptionをcatchしない
    • 正しくキャンセルさせない
    アプリケーション範囲のCoroutineScopeをDIする

    View full-size slide

  28. 参考⽂献
    • Mori Atsushi, 詳解 Kotlin Coroutines [ ], https://zenn.dev/at_sushi_at/books/edf adfc
    • Kotlin coroutines on Android | Android Developers, https://developer.android.com/kotlin/
    coroutines
    • Best practices for coroutines in Android | Android Developers, https://developer.android.com/
    kotlin/coroutines/coroutines-best-practices
    • Cancellation in coroutines. Cancellation and Exceptions in | by Florina Muntenescu | Android
    Developers | Medium, https://medium.com/androiddevelopers/cancellation-in-coroutines-
    aa b
    • Coroutines & Patterns for work that shouldn’t be cancelled | by Manuel Vivo | Android Developers |
    Medium, https://medium.com/androiddevelopers/coroutines-patterns-for-work-that-shouldnt-be-
    cancelled-e c f ad

    View full-size slide