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>).
Related
I have a challenge with converting the AsyncTask doInBackground process to RxJava. I would love to know how to convert this to Rx Java as none of what I've tried is working.
new AsyncTask<Void, Void, Integer>() {
#Override
protected Integer doInBackground(Void... voids) {
return mDAO.getCount();
}
#Override
protected void onPostExecute(Integer count) {
if (count == 0)
mCount.setText("All Notifications");
else
mCount.setText("New Notificaiton "+count);
}
}.execute();
And I tried this for Rx
Observable<Integer> count = Observable.fromCallable(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
return mDAO.getCount();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
count.subscribe(new Observer<Integer>() {
#Override
public void onSubscribe(Disposable d) {
mDisposable.add(d);
}
#Override
public void onNext(Integer integer) {
if (integer == 0)
mCount.setText("All Notifications");
else
mCount.setText("New Notification "+count);
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
I get this for instead of the count
Count io.reactivex.internal.operators.observable.ObservableObserveOn#5ccee5b
How do I solve this? Thank you.
Your implementation is why you're having this error. You should use a single callable instead. This should work 100% and let me know if you have any challenge with it.
Single.fromCallable(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
return mDAO.getCount();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess(new Consumer<Integer>() {
#Override
public void accept(Integer integer) throws Exception {
if (integer == 0)
mCount.setText("All Notifications");
else
mCount.setText("New Notification "+integer);
}
})
.doOnError(new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
}
})
.subscribe();
While inflating Android view I load a bunch of stuff from the background thread and inflate some views based on network responses. So I am trying to defer some of that tasks using RxJava like this
Single.fromCallable(() -> savedInstanceState)
.delay(50,TimeUnit.MICROSECONDS,AndroidSchedulers.mainThread())
.flatMapCompletable(this::loadVideos)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
Timber.d("on Subscribe");
}
#Override
public void onComplete() {
Timber.d("on onComplete");
}
#Override
public void onError(Throwable e) {
Timber.d("on onError");
}
});
And the loadVideos method is like this:
private Completable loadVideos(Bundle savedInstanceState) {
return Completable.fromAction(() -> {
videoPresenter.loadVideos(savedInstance);
});
}
What I am finding is onSubscribe() certainly gets called, but method videoPresenter.loadVideos never gets called. Would appreciate if anyone can point out what I am doing wrong.
For my testing, I implemented following test that seems to work...
public class DelayTest {
public static void main(String[] args) throws InterruptedException {
Single.fromCallable(() -> "hello")
.delay(50, TimeUnit.MICROSECONDS)
.flatMapCompletable(new Function<String, CompletableSource>() {
#Override
public CompletableSource apply(String s) throws Exception {
return getFlatMapCompletable();
}
})
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
System.out.println("In onSubscribe");
}
#Override
public void onComplete() {
System.out.println("In onComplete");
}
#Override
public void onError(Throwable e) {
System.out.println("In onError");
}
});
Thread.sleep(200L);
}
private static Completable getFlatMapCompletable() {
return Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
System.out.println("In flatmapCompletable");
}
});
}
}
Delay operator in RxJava is executed in another thread. So the rest of the execution does not wait for this one to be finished.
Take a look to some examples https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/utils/ObservableDelay.java
How can I get return value from bellow code :
CompositeDisposable mCompositeDisposable = new CompositeDisposable();
mCompositeDisposable.add(observableSubject(userName, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Consumer<Disposable>() {
#Override
public void accept(#NonNull Disposable disposable) throws Exception {
}
})
.doFinally(new Action() {
#Override
public void run() throws Exception {
}
})
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onComplete() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String res) {
//I need to get value from out of mCompositeDisposable.add(...)
Log.i("LOG", res);
}
}));
And :
private Observable<String> observableSubject(String userName, String password) {
return Observable.defer(() -> {
//Some Code
return Observable.just("Value");
});
}
I resolved my problem with EventBus in this method :
#Override
public void onNext(String res) {
//SomeCode ....
//.... EventBus.getDefault() ....
}
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() {
}
});