【Android/Kotlin】CoroutineExceptionHandlerでエラーハンドリングする方法

この記事からわかること
- Android StudioのKotlin Coroutinesの実装方法の使い方
- CoroutineExceptionHandlerでエラーハンドリングをするには?
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Meerkat
- Kotlin:2.0.21
公式リファレンス:Coroutine exceptions handling
Kotlin Coroutineの例外の伝播
Kotlin CoroutineのCoroutineBuilder(コルーチンビルダー)
は「自動で例外を伝播するもの」と「ユーザーが明示的に例外を受け取るもの」の2つに分かれます。CoroutineBuilder(コルーチンビルダー)
とはlaunch
やasync
などのコルーチン(非同期処理)を作成するものです。
コルーチンビルダー | 例外の扱い | エラーハンドリング |
---|---|---|
launch / actor | 自動で例外を伝播(uncaught) | CoroutineExceptionHandler |
async / produce | ユーザーが明示的に処理する必要あり | try〜catch |
例外の扱いによる処理の違いがエラーハンドリングの違いです。
CoroutineExceptionHandler
launch
などのコルーチンビルダーではCoroutineExceptionHandler
を使用して例外(エラー)をキャッチしてハンドリングします。使い方としては先にエラーハンドリング方法を定義しそれをコルーチンスコープやコルーチンビルダーごとに指定します。
コルーチンスコープ
コルーチンスコープごとに指定するには初期化する際にスレッドなどと共に指定できます。
val handler = CoroutineExceptionHandler { _, exception ->
println("エラー発生: ${exception.message}")
}
// スレッドと共にエラーハンドラも指定する
val scope = CoroutineScope(Dispatchers.Default + handler)
scope.launch {
throw RuntimeException("Task failed!")
}
コルーチンビルダー
コルーチンビルダーごとに指定するにはlaunchの引数に指定します。
val handler = CoroutineExceptionHandler { _, exception ->
println("エラー発生: ${exception.message}")
}
val scope = CoroutineScope(Dispatchers.Default)
scope.launch(handler) {
throw RuntimeException("Task failed!")
}
scope.launch(handler) {
throw RuntimeException("Task2 failed!")
}
asyncなどはtry〜catch文で例外を捕捉する
async
ではawait
するまで処理が動作しないため例外も発生しません。例外の補足はtry〜catch文
で行います。
// async: await するまで例外は発生しない
val deferred = async {
throw RuntimeException("asyncでのエラー")
}
try {
// ここで初めて例外が出る
deferred.await()
} catch (e: Exception) {
println("async: try-catchでキャッチ -> ${e.message}")
}
またtry〜catch文
の中でlaunch
を指定して例外が発生しても例外は捕捉できず、アプリがクラッシュします。
fun main() = runBlocking {
try {
launch {
// これは捕捉できずにエラーになる
throw RuntimeException("例外だよ")
}
} catch (e: Exception) {
println("エラー発生: ${e.message}")
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。