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

网络响应失败时如何为LiveData.setValue()设置合适值?

处理Retrofit请求异常时的LiveData状态设置

在网络请求失败或响应不成功时,直接给LiveData设置null会让UI层难以区分具体状态(是无数据、请求失败还是响应错误)。更合理的做法是用状态封装类包裹数据与状态信息,让LiveData传递明确的请求状态,方便UI层针对性处理。

1. 定义状态封装类

Kotlin 方案(推荐,密封类更简洁)

sealed class Resource<out T> {
    // 请求成功,携带返回数据
    data class Success<out T>(val data: T) : Resource<T>()
    // 请求失败/响应错误,携带错误信息和错误码(可选)
    data class Error(val message: String?, val code: Int? = null) : Resource<Nothing>()
    // 加载中状态(可选,用于显示加载UI)
    object Loading : Resource<Nothing>()
}

Java 方案

如果项目用Java开发,可以用包含状态枚举的通用类:

public class Resource<T> {
    private final Status status;
    private final T data;
    private final String message;
    private final Integer code;

    private Resource(Status status, T data, String message, Integer code) {
        this.status = status;
        this.data = data;
        this.message = message;
        this.code = code;
    }

    // 快捷创建成功状态实例
    public static <T> Resource<T> success(T data) {
        return new Resource<>(Status.SUCCESS, data, null, null);
    }

    // 快捷创建错误状态实例
    public static <T> Resource<T> error(String message, Integer code) {
        return new Resource<>(Status.ERROR, null, message, code);
    }

    // 快捷创建加载中状态实例
    public static <T> Resource<T> loading() {
        return new Resource<>(Status.LOADING, null, null, null);
    }

    // 请求状态枚举
    public enum Status {
        SUCCESS, ERROR, LOADING
    }

    // getter方法
    public Status getStatus() { return status; }
    public T getData() { return data; }
    public String getMessage() { return message; }
    public Integer getCode() { return code; }
}

2. 修改ViewModel中的LiveData类型

把原来的MutableLiveData<User>改成MutableLiveData<Resource<User>>,这样就能传递带状态的信息:

// ViewModel中的声明
private MutableLiveData<Resource<User>> userMutableLiveData = new MutableLiveData<>();

public LiveData<Resource<User>> getUserLiveData() {
    return userMutableLiveData;
}

3. 在Retrofit回调中设置对应状态

call.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        if (response.isSuccessful()) {
            // 请求成功,封装成功状态
            userMutableLiveData.setValue(Resource.success(response.body()));
        } else {
            // 响应不成功,解析错误信息
            String errorMsg = "请求失败";
            int errorCode = response.code();
            try {
                if (response.errorBody() != null) {
                    errorMsg = response.errorBody().string();
                }
            } catch (IOException e) {
                e.printStackTrace();
                errorMsg = "解析错误信息失败";
            }
            // 封装错误状态
            userMutableLiveData.setValue(Resource.error(errorMsg, errorCode));
        }
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
        // 网络请求失败,封装错误状态
        String errorMsg = t.getMessage() != null ? t.getMessage() : "网络连接失败";
        userMutableLiveData.setValue(Resource.error(errorMsg, null));
    }
});

4. UI层根据状态处理

在Activity/Fragment中观察LiveData,根据不同状态更新UI:

viewModel.getUserLiveData().observe(this, resource -> {
    switch (resource.getStatus()) {
        case SUCCESS:
            User user = resource.getData();
            // 更新UI显示用户数据
            break;
        case ERROR:
            String errorMsg = resource.getMessage();
            Integer errorCode = resource.getCode();
            // 显示错误提示,比如Toast或Snackbar
            String tip = errorCode != null ? errorMsg + " (错误码:" + errorCode + ")" : errorMsg;
            Toast.makeText(this, tip, Toast.LENGTH_SHORT).show();
            break;
        case LOADING:
            // 显示加载中UI,比如ProgressBar
            break;
    }
});

为什么这么做?

  • 避免null带来的歧义:UI层能明确区分“请求成功但无数据”“响应错误”“网络失败”等场景
  • 职责分离:数据模型(User)只承担数据存储,状态管理交给专门的封装类
  • 扩展性强:后续可以轻松添加更多状态(比如空数据状态)

内容的提问来源于stack exchange,提问作者Gaganjot Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 07:23:13