![_e4e6430f-590f-4134-ba92-9599bd114432](https://hackmd.io/_uploads/Hk2x12PsA.jpg) 在 Kotlin 中處理協程的例外時,確保正確處理例外並避免常見的陷阱是很重要的。 # **使用 `try-catch` 處理例外** - 如果你只是在協程中進行一般的例外處理,可以使用 `try-catch`。但要注意,`try-catch` 應該直接包住可能會拋出例外的代碼,而不是包住整個協程,這樣可以避免吞掉不應該被捕獲的例外,例如取消例外。 ```kotlin lifecycleScope.launch { try { // 可能拋出例外的代碼 val result = apiCall() // 處理結果 } catch (e: HttpException) { // 處理特定的 HTTP 例外 } } ``` ![Exception Coroutines](https://hackmd.io/_uploads/BkLMuivoC.jpg) # **使用 `CoroutineExceptionHandler`** - 如果你需要處理未捕獲的例外,你可以使用 `CoroutineExceptionHandler`。這是一個協程上下文,用來處理未捕獲的例外。你需要在最外層的協程中安裝這個處理器。 ```kotlin val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } lifecycleScope.launch(handler) { launch { // 可能會拋出未捕獲例外的代碼 throw RuntimeException("Something went wrong") } } ``` ![_72124e1f-7398-4779-bc4e-09a10471eb9e](https://hackmd.io/_uploads/H1oV12DsR.jpg) # **理解 `async` 的例外處理** - 當你使用 `async` 時,例外不會立即拋出,而是在調用 `await` 時才會拋出。因此,確保在調用 `await` 時正確處理例外。 ```kotlin val deferred = lifecycleScope.async { // 可能會拋出例外的代碼 throw RuntimeException("Something went wrong") } lifecycleScope.launch { try { val result = deferred.await() } catch (e: Exception) { println("Caught exception in async: $e") } } ``` ![_5f29a1c3-f9c3-45cc-9a5b-58e9733e567e](https://hackmd.io/_uploads/rkSXOswsA.jpg) # **使用 `supervisorScope` 避免協程相互影響** - 如果你不希望一個協程的失敗導致其他協程被取消,可以使用 `supervisorScope`。這樣即使一個協程失敗,其他協程仍然可以繼續執行。 ```kotlin supervisorScope { launch { // 這個協程失敗不會影響其他協程 throw RuntimeException("Failure in coroutine 1") } launch { // 即使前一個協程失敗,這個仍會繼續執行 println("Coroutine 2 is running") } } ``` ![_33909de2-9f66-47fb-8c0e-121cf07ab569](https://hackmd.io/_uploads/SJLHe2Pi0.jpg) # **避免吞掉取消例外** - 當你在協程中使用 `try-catch` 時,如果遇到 `CancellationException`,應該將其重新拋出,這樣可以確保協程正確地取消。 ```kotlin try { // 可能會拋出例外的代碼 } catch (e: Exception) { if (e is CancellationException) throw e // 處理其他例外 } ``` ![_a9c54660-9f69-4d92-b4c6-9db685f3955e](https://hackmd.io/_uploads/SJPBujwsA.jpg) # 總結 ![_0a3e1ac4-1c9b-46d8-a4a6-6420de8af4a5](https://hackmd.io/_uploads/rkfSy3Po0.jpg) 協程的例外處理與一般的同步程式不同,你需要特別注意例外的傳播方式和取消機制。使用正確的方式處理例外,不僅能保證程式的穩定性,還能避免一些隱藏的陷阱。 ![_28f31d3b-1c2d-4699-8b95-875ab22c1bb9](https://hackmd.io/_uploads/r1bH_ivsC.jpg)