I've the following chain of observables:
public Observable<Void> ApiCallBackObservable() {
return Observable.fromEmitter(new Action1<AsyncEmitter<Void>>() {
#Override
public void call(final AsyncEmitter<Void> voidAsyncEmitter) {
APICall.setCallBack(new CallBack() {
#Override
public void onResponseReceived() {
voidAsyncEmitter.onNext(null);
voidAsyncEmitter.onCompleted();
}
});
}
}, AsyncEmitter.BackpressureMode.NONE).timeout(100, TimeUnit.MILLISECONDS).onErrorResumeNext(new Func1<Throwable, Observable<? extends Void>>() {
#Override
public Observable<? extends Void> call(Throwable throwable) {
return Observable.empty();
}
});
}
The problem is that after this API callback i'm chaining more observables:
apiCallBackObservable().map(new Func1<Void, String>() {
#Override
public String call(Void aVoid) {
return "Ok";
}
}).flatmap(...).flatmap(....)....;
but somehow when the code hits the onErrorResumeNext(because of the timeout), the chain stops it never hits the next map, no error no anything it just stops.
Related
I try to write code call service API by RxJava2.
I have multiple API(included loop call API).
Here is my example code that i want.
My question is why onComplete haven't call?
Observable.just("test")
.flatMapCompletable(new Function<String, CompletableSource>() {
#Override
public CompletableSource apply(String s) throws Exception {
ArrayList<Observable<Void>> arrayList = new ArrayList<>();
arrayList.add(Completable.complete().delay(3, TimeUnit.SECONDS).andThen(new Observable<Void>() {
#Override
protected void subscribeActual(Observer<? super Void> observer) {
Log.e("subscribeActual", "onComplete1");
observer.onComplete();
}
}));
arrayList.add(Completable.complete().delay(1, TimeUnit.SECONDS).andThen(new Observable<Void>() {
#Override
protected void subscribeActual(Observer<? super Void> observer) {
Log.e("subscribeActual", "onComplete2");
observer.onComplete();
}
}));
arrayList.add(Completable.complete().delay(2, TimeUnit.SECONDS).andThen(new Observable<Void>() {
#Override
protected void subscribeActual(Observer<? super Void> observer) {
Log.e("subscribeActual", "onComplete3");
observer.onComplete();
}
}));
return Observable.merge(arrayList)
.toList()
.flatMapCompletable(new Function<List<Void>, CompletableSource>() {
#Override
public CompletableSource apply(List<Void> voids) throws Exception {
return Completable.complete();
}
});
}
})
.andThen(new Observable<Void>() {
#Override
protected void subscribeActual(Observer<? super Void> observer) {
Log.e("subscribeActual", "subscribeActual");
observer.onNext(null);
}
})
.flatMap(new Function<Void, ObservableSource<String>>() {
#Override
public ObservableSource<String> apply(Void aVoid) throws Exception {
Log.e("ObservableSource", "apply");
return Observable.just("Hello");
}
})
.flatMapCompletable(new Function<String, CompletableSource>() {
#Override
public CompletableSource apply(String s) throws Exception {
Log.e("apply", s);
return Completable.complete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onComplete() {
Log.e("onComplete", "onComplete");
}
#Override
public void onError(Throwable e) {
Log.e("onError", "onError " + e.getMessage());
}
});
And result from Log is
subscribeActual: onComplete2
subscribeActual: onComplete3
subscribeActual: onComplete1
subscribeActual: subscribeActual
ObservableSource: apply
apply: Hello
I expect chaining observable end with "Void" before subscribe(Completed or Observable<Void>).
I'm using RxAndroid for my app to send a request to the backend and handle the result.
public Observable<Response> getBrands() {
return new Observable<Response>() {
#Override
protected void subscribeActual(Observer<? super Response> observer) {
RequestHelper.GetRequest("getbrands");
}
};
}
public void GetBrands(){
getBrands().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Response>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Response value) {
Log.w("Reactive",value.toString());
Toast.makeText(getActivity(),"Yaaaaay request 5alas",Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Throwable e) {
Log.w("response brands= "+e.toString(),"MyTAG");
}
#Override
public void onComplete() {
}
});
}
RequestHelper.GetRequest("getbrands") is successfully called (Checked backend logs, it's called and returns the response.
the problem is onNext not getting called at all, neither the log or the toast shows up.
Anyone knows why ?
EDIT: i'm using this in a fragment where GetBrands() is called in oncreateview
Just changed my observable function to
public Observable<Response> getBrands() {
return Observable.fromCallable(new Callable<Response>() {
#Override
public Response call() throws Exception {
return RequestHelper.GetRequest("getbrands");
}
});
}
it's working now
Am doing a weather API call every 3secs and append the result to a textView using showWeather("weather") but I am sure there is a better way to do it. Am not sure why I need create Class Func1 but did because map required it. Also is there a way to shorten observer? I don't use lamda unfortunately. Any suggestions?
Observer myObserver = new Observer<String>() {
#Override
public void onError(Throwable e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
}
#Override
public void onComplete() {
}
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String value) {
showWeather(value);
}
};
class Func1<T, T1> implements io.reactivex.functions.Function<Long, String > {
#Override
public String apply(Long aLong) throws Exception {
return getJSON("http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1",300);
}
}
Observable.interval(3, TimeUnit.SECONDS)
.map(new Func1<Long, Observable<String>>() {
}).observeOn(AndroidSchedulers.mainThread()).subscribe(myObserver);
I tried :
Observable
.interval(3, SECONDS)
.subscribeOn(Schedulers.io())
.fromCallable(new Callable<String>() {
#Override
public String call() throws Exception {
return getJSON("http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1", 300);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(myObserver)
But I get :
03-07 21:47:25.982 21181-21181/com.alex.rxandroidexamples E/imerExampleFragment$1$1: null
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
Also how do I unsubscribe onPause or onPause?
I found out the best way to do this is :
private final CompositeDisposable disposables = new CompositeDisposable();
Observable fetchWeatherInterval = Observable.interval(3, TimeUnit.SECONDS)
.map(new Function<Long, String>() {
#Override
public String apply(Long aLong) throws Exception {
return getWeather("http://samples.openweathermap.org/data/2.5/weather?", "London,uk", "b1b15e88fa797225412429c1c50c122a1");
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
Observer displayWeatherInterval = new Observer<String>() {
#Override
public void onError(Throwable e) {
Log.e("Throwable ERROR", e.getMessage());
}
#Override
public void onComplete() {
}
#Override
public void onSubscribe(Disposable d) {
disposables.add(d);
}
#Override
public void onNext(String value) {
textViewWeatherInterval.append(value);
}
};
buttonFetchIntervalWeather.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
fetchWeatherInterval.subscribe(displayWeatherInterval);
}
});
I'm trying to run a long running task that might fail for some objects in a list I tried retry but it resubscribes to the entire list of observables. I can do nested subscriptions but it seems wrong. Is there any better solution than nesting subscriptions?
Here is my implementation:
public Observable<ReportItemModel> deferReports() {
return Observable.defer(new Callable<ObservableSource<? extends ReportItemModel>>() {
#Override
public ObservableSource<? extends ReportItemModel> call() throws Exception {
return Observable.fromIterable(getReports())
.map(new Function<Report, ReportItemModel>() {
#Override
public ReportItemModel apply(Report report) throws Exception {
return report.getReport();
}
});
}
});
}
reportFactory.deferReports()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.retry()
.subscribe(new Observer<ReportItemModel>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(ReportItemModel value) {
Log.d(TAG,value.toString());
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
I wanna create chain of request But it should looks that.
I call apiService.changePassword() and I can get success 200 and 401 error. If I get success then all is fine else I have to call apiService.refreshToken() and now If I get refreshed token I should call again apiService.changePassword(). I think about using retryWhen. What I should use?
[Edit:]
I got solution:
apiService.jobOffers(...)
.subscribeOn(Schedulers.io())
.flatMap(new Func1<Response<ResponseBody>, Observable<FeedDataProvider>>() {
#Override
public Observable<FeedDataProvider> call(Response<ResponseBody> response) {
...
}
}).retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
#Override
public Observable<?> call(Observable<? extends Throwable> observable) {
return observable.flatMap(new Func1<Throwable, Observable<?>>() {
#Override
public Observable<?> call(Throwable throwable) {
if(throwable instanceof RetrofitException) {
///refresh token
}
}
return Observable.error(throwable);
}
});
}
});