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

在Retrofit中使用RxJava的startWith方法传递状态遇语法错误求助

解决Retrofit+RxJava中用startWith传递加载状态的语法错误问题

我明白你遇到的问题了——直接给Retrofit返回的Flowable<Response<ResponseMobileGetAccess>>加startWith(Resource.Loading)会报类型不匹配的语法错误,这是因为**startWith要求发射的事件类型必须和原流的类型完全一致**,而你原流的类型是Retrofit的Response,但你想发送的是自定义的Resource状态类,两者类型不兼容。

下面是完整的解决方案,分步骤说明:

1. 先定义统一的状态封装类Resource

首先需要一个密封类(Kotlin)或抽象类(Java)来封装加载、成功、错误三种状态,确保整个流的事件类型统一:

Kotlin版本

sealed class Resource<out T> {
    // 加载状态,不需要携带数据
    object Loading : Resource<Nothing>()
    // 成功状态,携带返回数据
    data class Success<out T>(val data: T) : Resource<T>()
    // 错误状态,携带错误信息和异常对象
    data class Error(val message: String?, val throwable: Throwable?) : Resource<Nothing>()
}

Java版本

public abstract class Resource<T> {
    private Resource() {}

    public static class Loading<T> extends Resource<T> {}
    public static class Success<T> extends Resource<T> {
        public final T data;
        public Success(T data) { this.data = data; }
    }
    public static class Error<T> extends Resource<T> {
        public final String message;
        public final Throwable throwable;
        public Error(String message, Throwable throwable) {
            this.message = message;
            this.throwable = throwable;
        }
    }
}

2. 转换Retrofit流的类型并添加加载状态

现在需要把Retrofit返回的Response类型转换成Resource类型,再用startWith发送加载状态,这样类型就完全匹配了:

Kotlin调用示例

apiService.getAccess(url, requestModel)
    // 第一步:把Retrofit的Response转换成Resource状态
    .map { response ->
        if (response.isSuccessful) {
            // 成功且有返回体时,封装成Success状态
            response.body()?.let { Resource.Success(it) } 
                ?: Resource.Error("接口返回空数据", null)
        } else {
            // 接口返回错误码时,封装成Error状态
            Resource.Error("请求失败,错误码:${response.code()}", null)
        }
    }
    // 捕获网络请求中的异常,转换成Error状态(避免流终止)
    .onErrorReturn { throwable ->
        Resource.Error("网络异常:${throwable.message}", throwable)
    }
    // 现在可以安全添加加载状态了,因为流的类型已经是Resource<ResponseMobileGetAccess>
    .startWith(Resource.Loading)
    // 线程切换
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        { resource ->
            when (resource) {
                is Resource.Loading -> {
                    // 处理加载状态:显示loading弹窗、禁用按钮等
                }
                is Resource.Success -> {
                    // 处理成功数据:resource.data就是ResponseMobileGetAccess对象
                }
                is Resource.Error -> {
                    // 处理错误状态:显示错误提示、隐藏loading等
                }
            }
        },
        {
            // 这里理论上不会走到(因为onErrorReturn已经捕获了异常),可以留作兜底处理
        }
    )

Java调用示例

apiService.getAccess(url, requestModel)
        .map(response -> {
            if (response.isSuccessful()) {
                ResponseMobileGetAccess body = response.body();
                if (body != null) {
                    return new Resource.Success<>(body);
                } else {
                    return new Resource.Error<>("接口返回空数据", null);
                }
            } else {
                return new Resource.Error<>("请求失败,错误码:" + response.code(), null);
            }
        })
        .onErrorReturn(throwable -> new Resource.Error<>("网络异常:" + throwable.getMessage(), throwable))
        .startWith(new Resource.Loading<>())
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(resource -> {
            if (resource instanceof Resource.Loading) {
                // 处理加载状态
            } else if (resource instanceof Resource.Success) {
                ResponseMobileGetAccess data = ((Resource.Success<ResponseMobileGetAccess>) resource).data;
                // 处理成功数据
            } else if (resource instanceof Resource.Error) {
                Resource.Error error = (Resource.Error) resource;
                // 处理错误状态
            }
        }, throwable -> {
            // 兜底错误处理
        });

关键注意点

  • 类型统一是核心:必须先把Retrofit的Response流转换成Resource类型,再调用startWith,否则会因为类型不匹配报错。
  • 异常处理:用onErrorReturn捕获网络异常并转换成Error状态,这样整个流不会因为异常中断,能完整传递错误状态到订阅端。
  • Loading状态的泛型适配:Kotlin中用Nothing作为Loading的泛型,Java中用通配符适配,确保它能和Success/Error的泛型兼容。

内容的提问来源于stack exchange,提问作者Mehdi Jahed Manesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:06:32