问题描述
Helllo,
getInfo()服务调用由多个片段同时订阅,所以我只想调用一次服务,存储该信息并返回。
我通过使用blockingGet()找到了解决方案
adddisposable(getInfoUseCase().get()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(info -> {},throwable -> {}));
最终翻译为:
private var info: InfoEntity? = null
override fun getInfo(): Single<InfoEntity> {
return if (info== null) {
Single.just(service.getInfo(SERVICE_GET_INFO).blockingGet())
.map { mapper.transform(it) }
.doOnSuccess {
info = it
}
} else {
return Single.just(info)
}
}
这是服务对象:
Retrofit restAdapter = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(createClient(TIMEOUT,true))
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.build();
service = restAdapter.create(RetrofitService.class);
@GET(".")
Single<ApiResponse<InfoEntity>> getInfo(
@Query(SERVICE_ID) String serviceId
);
乍看之下,一切正常,但后来我找到了这个答案:
never use observeOn(AndroidSchedulers.mainThread()) with blockingGet()
但就我而言,一切正常,我没有什么区别,我的方法是否有问题?如果是这样,那有什么出路?
解决方法
问题是您正在阻塞主线程。这意味着当您等待网络通话时(可能需要5秒钟),UI将被完全冻结,并且用户将无法执行任何操作。这真的不是一个很棒的用户体验。
此修复程序很棘手。 BehaviorSubject
在这里很有用,因为它允许在网络调用获取期间订阅的所有片段都接收结果通知。
// I assume these variables are in a singleton? Otherwise they won't be much use
private var subject: BehaviorSubject<InfoEntity> = BehaviorSubject.create()
var isFetching = false
override fun getInfo(): Single<InfoEntity> {
// If the network call previously failed,reset the subject to a new empty one,so that this subscriber and future ones can receive a value
if (subject.hasThrowable() || subject.hasComplete()) {
subject = BehaviorSubject.create()
}
if (!subject.hasValue() && !isFetching) {
isFetching = true
fetch()
}
return subject.firstOrError()
}
private fun fetch() {
fetchInfo()
.doFinally {
isFetching = false
}
.subscribe(
{
subject.onNext(it)
},{
subject.onError(it)
})
}