CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap
Pasang CoroutineExceptionHandler untuk mencatat atau memulihkan diri dari exception yang tidak tertangani.
CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap adalah pelajaran Kotlin Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Kotlin Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Kotlin Academy mencakup 4 pelajaran total.
Apa Itu CoroutineExceptionHandler?
CoroutineExceptionHandler adalah elemen konteks yang menangani pengecualian yang tidak tertangani dari korutin yang tidak memiliki penanganan untuk menangkapnya. Elemen ini berfungsi sebagai pilihan terakhir.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { context, exception ->
println("Caught unhandled: ${exception.message}")
}
fun main() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default + handler)
scope.launch { throw RuntimeException("oops") }
delay(100)
}Hanya untuk Korutin Akar
CoroutineExceptionHandler hanya menangkap pengecualian dari korutin akar (yang diluncurkan langsung pada suatu cakupan). Korutin anak meneruskan pengecualian ke induknya, bukan ke penangan.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Root coroutine — handler fires:
CoroutineScope(handler).launch {
throw RuntimeException("root error")
}
delay(100)
// NOT handler (child of coroutineScope):
// launch { launch { throw RuntimeException() } }
}Tidak Menyembunyikan Pengecualian
Penangan dipanggil setelah pengecualian tersebut membatalkan korutin. Penangan ini digunakan untuk pencatatan log, pelaporan kerusakan, atau pembersihan—bukan untuk melanjutkan eksekusi.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e ->
println("[CrashReport] ${e::class.simpleName}: ${e.message}")
// send to Crashlytics, Sentry, etc.
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).apply {
launch { throw IllegalStateException("state error") }
launch { delay(100); println("still alive") }
delay(200)
cancel()
}
}Penangan + SupervisorJob
Kombinasi SupervisorJob + CoroutineExceptionHandler adalah pola standar untuk cakupan berumur panjang: tugas anak gagal secara independen, dan kegagalan yang tidak tertangani dicatat.
import kotlinx.coroutines.*
class AppScope {
private val handler = CoroutineExceptionHandler { _, e ->
println("Uncaught: ${e.message}")
}
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
}
fun main() = runBlocking {
val app = AppScope()
app.scope.launch { throw RuntimeException("task failed") }
app.scope.launch { delay(100); println("other task ok") }
delay(200)
app.scope.cancel()
}Penanganan dengan Operasi Asinkron
Untuk async, pengecualian disimpan dalam Deferred dan dilemparkan saat await(). Penangan TIDAK aktif untuk operasi asinkron kecuali nilai tertundanya tidak ditunggu.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob() + handler)
val deferred = scope.async { throw RuntimeException("async error") }
try {
deferred.await() // exception thrown here
} catch (e: RuntimeException) {
println("Caught from await: ${e.message}")
}
delay(50)
scope.cancel()
}Perbandingan Thread.UncaughtExceptionHandler
Tidak seperti UncaughtExceptionHandler milik Java, penangan milik Kotlin merupakan bagian dari konteks korutin dan hanya berlaku di dalam korutin pada cakupan tersebut.
import kotlinx.coroutines.*
// Java style (applies to threads):
Thread.setDefaultUncaughtExceptionHandler { t, e ->
println("Thread ${t.name} threw: ${e.message}")
}
// Kotlin coroutine style (applies to coroutines in scope):
val handler = CoroutineExceptionHandler { _, e ->
println("Coroutine threw: ${e.message}")
}
fun main() = runBlocking { println("Handlers target different concurrency models") }Pola Pencatatan Log dengan MDC
Dalam aplikasi server, penangan dapat menangkap informasi konteks korutin (seperti ID permintaan) untuk pencatatan log terstruktur sebelum meneruskannya ke kerangka kerja pencatatan log.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { ctx, e ->
val jobName = ctx[CoroutineName]?.name ?: "unknown"
println("[${jobName}] ERROR: ${e.message}")
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).launch(CoroutineName("DataLoader")) {
throw RuntimeException("fetch failed")
}
delay(100)
}Integrasi Pelaporan Kerusakan
Gunakan penangan untuk meneruskan pengecualian yang tidak tertangani ke layanan pelaporan kerusakan seperti Firebase Crashlytics atau Sentry.
import kotlinx.coroutines.*
object CrashReporter {
fun record(e: Throwable) = println("[Crashlytics] ${e.message}")
}
val handler = CoroutineExceptionHandler { _, e ->
if (e !is CancellationException) CrashReporter.record(e)
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
fun main() = runBlocking {
appScope.launch { throw RuntimeException("unhandled in production") }
delay(100)
appScope.cancel()
}Pewarisan Penangan
Penangan dari konteks induk TIDAK diwariskan secara otomatis oleh korutin anak. Penangan tersebut harus berada di konteks korutin akar agar dapat aktif.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Handler only fires at root level:
CoroutineScope(SupervisorJob() + handler).launch {
// Child of root — exception propagates to root handler:
launch { throw RuntimeException("nested") }
}
delay(100)
}Ringkasan Praktik Terbaik
Selalu pasang CoroutineExceptionHandler pada cakupan tingkat aplikasi atau tingkat fitur. Catat setiap pengecualian selain pembatalan. Jangan pernah mengandalkannya untuk alur kontrol—penangan ini hanya untuk observabilitas.
import kotlinx.coroutines.*
val globalHandler = CoroutineExceptionHandler { ctx, e ->
if (e !is CancellationException) {
println("[ERROR] ${ctx[CoroutineName]?.name}: ${e.message}")
}
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + globalHandler)
fun main() = runBlocking {
appScope.launch(CoroutineName("Auth")) { throw RuntimeException("token expired") }
delay(100); appScope.cancel()
}Pemeriksaan Singkat
Untuk jenis korutin apa CoroutineExceptionHandler TIDAK otomatis aktif?
Ringkasan
CoroutineExceptionHandler adalah pengamat pilihan terakhir untuk pengecualian yang tidak tertangani dalam korutin akar. Gabungkan dengan SupervisorJob untuk cakupan berumur panjang. Gunakan untuk pencatatan log dan pelaporan kerusakan—jangan pernah untuk alur kontrol.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap” gratis?
Ya — teks lengkap “CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Kotlin Academy, upgrade ke CoddyKit PRO. Kursus Kotlin Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap”?
Pasang CoroutineExceptionHandler untuk mencatat atau memulihkan diri dari exception yang tidak tertangani. Kamu berlatih Kotlin Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Kotlin Academy?
Tidak diperlukan pengalaman sebelumnya. Kotlin Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.
Berapa lama pelajaran “CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Kotlin Academy ini?
Ya. Setiap pelajaran Kotlin Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- SupervisorJob vs Job: Isolasi Kegagalan
- CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap
- Propagasi Exception async/await
- Merancang Arsitektur Coroutine yang Tangguh