Retrofit结合RxJava使用时Observer无法捕获返回值如何解决
问题原因
- 异步执行时序问题
不管是原生Retrofit的enqueue回调还是RxJava的订阅回调,都是执行在后台线程,你的search方法执行到return d时,网络请求还未完成,变量d还没被赋值,所以返回值必然为空。
你看到原生版本能正常打印回调日志,RxJava版本没有输出,是因为RxJava的回调执行在IO子线程,如果你的宿主进程(比如main方法执行结束、测试用例跑完)提前退出,子线程会被直接销毁,还没来得及执行回调逻辑。
- 异步执行时序问题
- 冗余配置(不影响功能,属于可优化项)
你已经在RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())全局指定了订阅线程为IO线程,后续调用subscribeOn(Schedulers.io())属于重复配置。
- 冗余配置(不影响功能,属于可优化项)
解决方案
根据你的使用场景选择对应方案:
方案1:同步阻塞获取返回值(适合测试、后台任务场景,禁止在安卓主线程使用)
直接用RxJava的toBlocking方法将Observable转为阻塞调用,等待请求完成后直接返回结果,代码修改如下:
private fun <T> search(call: rx.Observable<T>?): T? { return call?.doOnNext { value -> println("d") println(value) }?.doOnError { println("error") }?.doOnCompleted { println("Completed") }?.toBlocking()?.first() }
方案2:异步回调处理(推荐,适合安卓等需要异步执行的场景)
不要通过方法返回值拿结果,改用回调传递请求结果,安卓场景下可以加切主线程的逻辑方便更新UI:
// 增加回调参数接收结果 private fun <T> search( call: rx.Observable<T>?, onSuccess: (T) -> Unit, onError: (Throwable) -> Unit = {} ) { call ?: return call.observeOn(AndroidSchedulers.mainThread()) // 安卓环境需要切主线程,非安卓可删除 .subscribe( { value -> println("d") println(value) onSuccess(value) }, { throwable -> println("error") onError(throwable) }, { println("Completed") } ) } // 调用示例 fun listingSearch(qrCode: Int) { val o = AsRetroFitAPIClient.apiInterface.listingSearch(qrCode) search(o, onSuccess = { person -> // 此处处理请求成功的业务逻辑 }, onError = { throwable -> // 此处处理请求失败逻辑 } ) }
注意:安卓环境使用RxJava需要额外引入RxAndroid依赖才能使用
AndroidSchedulers.mainThread()。
额外优化建议
你的AsApi接口中listingSearch方法的返回值类型可以改为非空的Observable<Person>,Retrofit生成的实现不会返回null,可避免不必要的空判断。
内容的提问来源于stack exchange,提问作者Veerabala J
相关产品推荐
相关产品推荐

