تكرار السؤال: …
الإجابة المختصرة
يعمل كصمام أمان أخير (Global Catch) لالتقاط الاستثناءات غير المعالجة في الـ Root Coroutine المطلقة بواسطة launch لمنع كراش التطبيق.
الشرح
يُثبت CoroutineExceptionHandler على مستوى الـ CoroutineScope أو الـ Root Job. لا يمنع المعالج إلغاء الكوروتين نفسه أو انتشار الفشل للأب في الـ Job العادية، لكنه يوفر مكانًا مركزيًا لتسجيل الخطأ (Logging) وعرض رسالة للمستخدم بدلاً من انهيار التطبيق. لا يؤثر المعالج على async لأنه يحتفظ بالاستثناء داخل كائن Deferred ليرميه عند await().
مثال بالكود
val handler = CoroutineExceptionHandler { _, exception ->
Log.e("Coroutines", "Caught unhandled exception: $exception")
}
val scope = CoroutineScope(Dispatchers.Main + Job() + handler)
scope.launch {
throw RuntimeException("Network crash!") // يلتقطه handler بأمان
}أخطاء شائعة
- محاولة تثبيت CoroutineExceptionHandler داخل كوروتين ابن (Child Coroutine)، حيث يتجاهله النظام ولا يستجيب إلا إذا كان على الـ Root.
- توقع أن يمنع المعالج الكوروتين الفاشل من إيقاف بقية العمليات المرتبطة به في الـ Standard Job.