Kotlin

Kotlin Coroutines の例外伝搬とハンドリング完全ガイド

ⓘ本ページはプロモーションが含まれています

お得なお知らせ

スポンサードリンク
AI時代のキャリア構築

プログラミング学習、今日から動き出す

「何から始めるか」で止まっている人こそ、無料説明会や本で自分に合うルートを30分で確定できます。

Enjoy Tech!|月額制でWeb系に強い▶ (Kindle本)ITエンジニアの転職学|後悔しないキャリア戦略▶

▶ AIコーディング環境なら  実践Claude Code入門(Amazon)が実務で即使える入門書です。Amazonベストセラーにも選ばれていますよ。


スポンサードリンク

1. 例外伝搬の基本構造(CancellationException を含む)

Kotlin のコルーチンは 構造化並行性 に基づき、子コルーチンが例外を送出するとその例外は直近の共通スコープまで上がります。
このとき CancellationException は「正常なキャンセル」とみなされ、通常の例外とは別に扱われます。

1‑1. キャンセルと例外の違い

項目 通常例外 (Throwable) CancellationException
発生タイミング 任意(ロジックエラー、IO エラー等) コルーチンが キャンセル されたときに自動的にスロー
伝搬先 例外ハンドラまたは最上位の CoroutineExceptionHandler に届く キャンセル対象の子・親コルーチン全体で捕捉され、invokeOnCancellation が呼び出される
デフォルト動作 未処理ならアプリがクラッシュ コルーチンは即座に終了し、例外としては扱われない(isActivefalse になる)

ポイント
キャンセルは「失敗」ではなく「途中で止める」意図のシグナルです。
したがって、catch (e: CancellationException) と書くとキャンセル自体を誤ってエラー扱いしてしまうことがあります。

1‑2. 実装例(インポート・スコープの明示)

  • runBlocking が最上位スコープになるので、例外はここまで伝搬します。
  • finally ブロックで子2 のキャンセルが確認でき、invokeOnCompletion では CancellationException が原因として渡されます。

2. CoroutineExceptionHandler の正しい使い方

2‑1. 基本概念とスコープの選択

  • 構造化されたスコープviewModelScope, lifecycleScope, supervisorScope)内でハンドラを設定すれば、未捕捉例外は一元管理できます。
  • GlobalScopeトップレベルかつライフサイクルが切り離された スコープのため、ハンドラを付与しても UI コンポーネントから制御できません。

2‑2. 実装例(ViewModel)

  • viewModelScope が自動的に ViewModel の破棄と同時にキャンセルされるため、リークの心配がありません。
  • ハンドラは コルーチン単位 で設定でき、複数ハンドラを組み合わせても問題ありません(+ 演算子で結合可能)。

2‑3. GlobalScope の落とし穴

  • GlobalScope のコルーチンは アプリ全体のライフサイクル に紐付かないため、画面が破棄されたあとも残り続けます。
  • 例外がハンドラで捕捉されても UI が存在しないケースではユーザーへの通知手段が失われる点に注意してください。

3. SupervisorJobsupervisorScope の使いどころ

3‑1. 子コルーチンの失敗を分離する仕組み

スコープ 子の例外が親に伝搬するか 同一スコープ内の他子への影響
CoroutineScope(Job())(デフォルト) Yes(キャンセル連鎖) Yes(全体がキャンセル)
SupervisorJob() または supervisorScope No(例外は親に伝搬しない) No(他の子はそのまま実行)

3‑2. 実装例

  • 子A が例外を投げても、子B はキャンセルされずに最後まで実行されます。
  • supervisorScope { … } を使うと同様の効果が得られ、スコープ生成がシンプルになります。


4. try‑catchrunCatching / Result の併用

4‑1. Resultクラス ではなく 型エイリアス

Kotlin 標準ライブラリの Result<T> には SuccessFailure クラスは存在しません。代わりに次の拡張関数を利用します。

関数 説明
isSuccess / isFailure 成功・失敗判定
getOrNull() 成功時だけ値を取得(失敗時は null
exceptionOrNull() 失敗時の例外を取得
fold(onSuccess, onFailure) 成功と失敗それぞれにハンドラを提供

4‑2. 正しいサンプルコード

  • runCatching が例外を捕捉し、Result に変換します。
  • 呼び出し側は 例外処理と成功時ロジックを分離 できるため、テストが容易になります。

4‑3. try‑catch と併用すべきケース

シナリオ 推奨手法
非同期 API の失敗だけをハンドルしたい runCatchingResult
複数の例外型に対して個別処理が必要 従来の try‑catchwhen (e) { is IOException -> … }
キャンセル例外は無視したい catch (e: CancellationException) { throw e } で再スロー

5. Android 標準スコープ活用のベストプラクティス

5‑1. viewModelScopelifecycleScope の共通パターン

  • viewModelScope が ViewModel の寿命に合わせて自動キャンセルされ、メモリリークが防げます。
  • CoroutineExceptionHandlerResult を組み合わせると 例外情報の一元管理成功時データ取得 が同時に実現できます。

5‑2. lifecycleScope の使用例(Fragment)

  • lifecycleScope は Fragment の ViewLifecycle に合わせて自動キャンセルされます。
  • launchWhenStarted を使うと、Fragment が STARTED 状態になるまでコレクションが保留され、不要な UI 更新を防げます。

5‑3. GlobalScope は原則使用しない

問題点 具体例
ライフサイクルと切り離された実行 アプリがバックグラウンドに回ってもタスクが残る
メモリリークの温床 Context を保持したまま解放できない
例外ハンドリングが困難 UI が存在しないため通知手段が失われる

代替案
短時間タスク → viewModelScope / lifecycleScope
長時間バックグラウンド処理 → WorkManager(または ForegroundService


6. まとめと次のアクション

項目 キーポイント
例外伝搬 スコープ階層に沿って上がり、CancellationException はキャンセルフローとして別扱い。
ハンドラ CoroutineExceptionHandler は UI スコープで設定し、未捕捉例外を一元管理。
SupervisorJob 子の失敗が他に波及しない構造化並行性を実現できる。
Result API runCatching と標準的な Result 拡張関数で、成功・失敗を型安全に扱う。
Android 標準スコープ viewModelScopelifecycleScope を活用し、GlobalScope は避ける。
キャンセル例外 必要がなければ捕捉せず再送出し、意図しないエラー扱いを防止する。

今すぐできること

  1. プロジェクトの全コルーチン呼び出し箇所viewModelScopelifecycleScope に統一する。
  2. 未捕捉例外があるファイルに CoroutineExceptionHandler を追加し、ログや UI 通知を実装。
  3. 失敗が他タスクに影響しないケースは SupervisorJob(または supervisorScope)へ置き換える。
  4. API 呼び出し層で runCatching { … } を導入し、戻り値を Result<T> に統一する。
  5. CancellationException が捕捉されたら必ず再スローし、キャンセルが正しく伝搬することを確認。

最新情報は公式ドキュメント(kotlinlang.org/docs/coroutines-exception-handling.html)や Kotlin 1.9 のリリースノートで随時チェックしてください。


スポンサードリンク

お得なお知らせ

スポンサードリンク
AI時代のキャリア構築

プログラミング学習、今日から動き出す

「何から始めるか」で止まっている人こそ、無料説明会や本で自分に合うルートを30分で確定できます。

Enjoy Tech!|月額制でWeb系に強い▶ (Kindle本)ITエンジニアの転職学|後悔しないキャリア戦略▶

▶ AIコーディング環境なら  実践Claude Code入門(Amazon)が実務で即使える入門書です。Amazonベストセラーにも選ばれていますよ。


-Kotlin