使用LiveData{}时如何处理网络超时/无网络导致的应用崩溃?
解决方案
核心问题是liveData块中未捕获网络请求抛出的异常,导致应用崩溃。我们可以通过封装状态类+异常捕获来处理,实现错误状态的传递和用户提示。
1. 定义状态密封类
先创建一个密封类,用来封装请求的不同状态(成功、无网络、其他错误):
sealed class AuthResult<out T> { data class Success<out T>(val data: T) : AuthResult<T>() object NoNetwork : AuthResult<Nothing>() data class Error(val exception: Throwable) : AuthResult<Nothing>() }
2. 修改ViewModel中的LiveData逻辑
在liveData块中用try-catch捕获异常,根据异常类型判断是否为无网络情况,然后emit对应的状态:
fun getAuthenticationBrieInfo() = liveData { try { val data = authenticationRepository.getAuthenticationBrieInfo() emit(AuthResult.Success(data)) } catch (e: Exception) { // 根据异常类型判断是否为无网络 if (e is java.net.ConnectException || e is java.net.SocketTimeoutException) { emit(AuthResult.NoNetwork) } else { emit(AuthResult.Error(e)) } } }
3. 在Fragment中处理状态
观察LiveData时,根据不同状态做出响应,比如显示无网络提示:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) authenticationViewModel.getAuthenticationBrieInfo().observe(viewLifecycleOwner) { result -> when (result) { is AuthResult.Success -> { // 处理成功返回的数据 val data = result.data } AuthResult.NoNetwork -> { // 显示无网络提示,比如Toast或Snackbar Toast.makeText(requireContext(), "无网络", Toast.LENGTH_SHORT).show() } is AuthResult.Error -> { // 处理其他错误,比如打印日志或显示通用错误提示 Log.e("AuthError", "请求失败", result.exception) Toast.makeText(requireContext(), "请求失败,请稍后重试", Toast.LENGTH_SHORT).show() } } } }
补充说明
- 如果你的Repository已经封装了网络状态判断,可以直接返回类似
AuthResult的状态,ViewModel层就不需要额外捕获异常了。 - 对于网络异常的判断,除了
ConnectException和SocketTimeoutException,还可以根据你使用的网络框架(比如Retrofit)的自定义异常来调整。
内容的提问来源于stack exchange,提问作者史新雨
相关产品推荐
相关产品推荐

