You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中使用Retrofit2+Hilt如何处理断网场景下的网络错误响应?

离线网络错误处理方案

1. 网络状态前置检查

发起请求前先判断设备联网状态,避免无意义请求触发崩溃:

  • 先在AndroidManifest.xml添加必要权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  • 封装网络状态检测工具类,可通过Hilt注入到需要调用的位置,无网络时直接返回错误提示,不发起请求。

2. 统一捕获请求异常

离线时Retrofit会抛出IOException,未捕获就会直接崩溃,建议用密封类封装请求结果,在Repository层统一处理异常:

  • 定义请求结果密封类:
sealed class Result<out T> {
    data class Success<out T>(val data: T): Result<T>()
    data class Error(val errorMsg: String, val exception: Exception? = null): Result<Nothing>()
}
  • 封装请求逻辑统一捕获异常:
suspend fun getRecipeList(): Result<List<Recipe>> {
    return try {
        val response = recipeService.getList()
        Result.Success(response.data)
    } catch (e: IOException) {
        Result.Error("当前无网络,请检查连接后重试", e)
    } catch (e: Exception) {
        Result.Error("请求失败,请稍后重试", e)
    }
}

3. UI层适配错误状态

ViewModel把处理好的状态暴露给Compose层,展示对应错误提示即可:

  • ViewModel中定义UI状态:
val recipeUiState = MutableStateFlow<RecipeUiState>(RecipeUiState.Loading)

sealed class RecipeUiState {
    object Loading: RecipeUiState()
    data class Success(val data: List<Recipe>): RecipeUiState()
    data class Error(val msg: String): RecipeUiState()
}

fun fetchRecipe() = viewModelScope.launch {
    recipeUiState.value = RecipeUiState.Loading
    val result = recipeRepository.getRecipeList()
    recipeUiState.value = when(result) {
        is Result.Success -> RecipeUiState.Success(result.data)
        is Result.Error -> RecipeUiState.Error(result.errorMsg)
    }
}
  • Compose层监听状态,错误时展示Toast或者全屏错误提示页即可。

4. 可选:添加离线缓存

如果需要离线也能查看历史数据,可以修改你提供的Retrofit配置,搭配OkHttp缓存实现离线读取:

@Singleton
@Provides
fun provideRecipeService(@ApplicationContext context: Context) : RecipeService {
    // 配置100M缓存空间
    val cache = Cache(context.cacheDir, 100L * 1024 * 1024)
    val okHttpClient = OkHttpClient.Builder()
        .cache(cache)
        .addInterceptor { chain ->
            val request = if (isNetworkAvailable(context)) {
                // 有网时缓存1小时
                chain.request().newBuilder()
                    .header("Cache-Control", "public, max-age=3600")
                    .build()
            } else {
                // 无网时读取7天内的缓存
                chain.request().newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=604800")
                    .build()
            }
            chain.proceed(request)
        }
        .build()

    return Retrofit.Builder()
        .baseUrl("https://food2fork.ca/api/recipe/")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(RecipeService::class.java)
}

内容的提问来源于stack exchange,提问作者Jeevan Rupacha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:36:03