Reputation: 536
I'm working with rxjava2
.
My problem is that sometimes server sends me nothing (response body is null, and so on List size = 0), so in that case I'd like to repeat request after 5 sec.
I have an Retrofit2
request:
@GET("/ics/api/{bidId}/calltracking/reports/widgets")
Single<List<CallTrackingWidget>> getWidgets(@Path("bidId") int bidId);
Use it like so:
RetrofitFactory.getRetrofitService().getWidgets(mDataManager.getBidId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(widgets -> getView().showLoading())
.doOnSuccess(widgets -> getView().hideLoading())
.repeatWhen(widgets -> widgets.flatMap(size -> {
if ((int) size == 0) {
return Flowable.just("asd").delay(5, TimeUnit.SECONDS);
} else {
return widgets;
}
}))
.subscribe(widgets -> {
mDataManager.getProduct().getCallTrackingData().setWidgets(widgets);
getView().initWidgets(mDataManager.getProduct().getCallTrackingData().getWidgetNames());
}, throwable -> {
handleError(throwable, R.string.error_internet);
})
But my code a have an exeption:
android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
Help me please to repeat request after 5 sec, when List size is 0.
Upvotes: 0
Views: 774
Reputation: 1
Because you don't deal with the view on main thread, you can write like this:
RetrofitFactory.getRetrofitService().getWidgets(mDataManager.getBidId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(widgets -> getView().showLoading())
.subscribeOn(AndroidSchedulers.mainThread())
.repeatWhen(widgets - > widgets.flatMap(size - > {
if ((int) size == 0) {
return Flowable.just("asd").delay(5, TimeUnit.SECONDS);
} else {
return widgets;
}
}))
.subscribe(widgets - > {
getView().hideLoading(); // Hide loading view
mDataManager.getProduct().getCallTrackingData().setWidgets(widgets);
getView().initWidgets(mDataManager.getProduct().getCallTrackingData().getWidgetNames());
}, throwable - > {
getView().hideLoading(); // Hide loading view
handleError(throwable, R.string.error_internet);
})
Upvotes: 0
Reputation: 3702
I think your problem lies in these two lines:
.doOnSubscribe(widgets -> getView().showLoading())
.doOnSuccess(widgets -> getView().hideLoading())
These two actions will execute off the Main thread. And as the exception implies, you can only touch Android views from the Main thread.
Try moving this view manipulation somewhere else. Like this:
getView().showLoading(); // Show loading view
RetrofitFactory.getRetrofitService().getWidgets(mDataManager.getBidId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.repeatWhen(widgets - > widgets.flatMap(size - > {
if ((int) size == 0) {
return Flowable.just("asd").delay(5, TimeUnit.SECONDS);
} else {
return widgets;
}
}))
.subscribe(widgets - > {
getView().hideLoading(); // Hide loading view
mDataManager.getProduct().getCallTrackingData().setWidgets(widgets);
getView().initWidgets(mDataManager.getProduct().getCallTrackingData().getWidgetNames());
}, throwable - > {
getView().hideLoading(); // Hide loading view
handleError(throwable, R.string.error_internet);
})
Upvotes: 1