开启飞行模式时Android App触发DeadObjectException崩溃求助
问题分析与解决方案
核心问题
开启飞行模式时,网络请求会抛出未捕获的IO异常,而viewModelScope中未处理的异常会直接导致应用崩溃。你看到的DeadObjectException是应用崩溃后系统层面的错误,并非真正的崩溃根源——真正的异常发生在repository.getAllCountries()调用时,因为没有捕获,协程直接终止并触发应用崩溃,导致后续日志无法打印。
修复代码
修改CountryListViewModel中的getAllCountries方法,添加异常捕获逻辑:
fun getAllCountries() { if (_countryList.value.isNotEmpty() || _loading.value) return viewModelScope.launch(Dispatchers.IO) { try { withContext(Dispatchers.Main) { _loading.value = true } val response = repository.getAllCountries() withContext(Dispatchers.Main) { if (response.isSuccessful) { response.body()?.let { _countryList.value = it } } else { onError("Error : ${response.message()} ") } _loading.value = false } } catch (e: Exception) { // 处理网络不可用、超时等异常 withContext(Dispatchers.Main) { onError("网络连接失败: ${e.localizedMessage}") } } } }
额外优化建议
- 统一线程调度:把所有StateFlow的更新操作放到
Dispatchers.Main中,避免线程切换混乱。 - Repository层封装:建议让Repository的网络请求返回密封类,而非直接抛出异常,让ViewModel处理更清晰:
这样ViewModel中就无需额外try-catch,直接处理密封类结果即可。// 示例密封类 sealed class NetworkResult<out T> { data class Success<out T>(val data: T) : NetworkResult<T>() data class Error(val message: String) : NetworkResult<Nothing>() } // Repository中修改 suspend fun getAllCountries(): NetworkResult<List<Country>> { return try { val response = apiService.getCountries() if (response.isSuccessful) { response.body()?.let { NetworkResult.Success(it) } ?: NetworkResult.Error("空响应") } else { NetworkResult.Error(response.message()) } } catch (e: Exception) { NetworkResult.Error(e.localizedMessage ?: "未知错误") } }
关键说明
viewModelScope的特性是:如果协程中抛出未捕获的异常,会直接终止应用进程。所以所有可能抛出异常的挂起函数调用,都必须用try-catch包裹,或者在Repository层提前处理异常。
内容的提问来源于stack exchange,提问作者Hack123
相关产品推荐
相关产品推荐

