I need help for RxJava. Everything is working fine. But I want to call onNext manually in my other method.
Observable<Data> mylist = Observable.fromIterable(datalist);
mylist.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.buffer(6)
.subscribe(new Observer<List<Data>>() {
#Override
public void onSubscribe(Disposable d) { }
#Override
public void onNext(List<Data> list) {
myadapter.addData(list);
}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() { fetchNextPage(); }
});
Like this:
OnloadMore() {
onNext()
}
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
Few days ago I have faced with the treading rx problem. I was thinking how the rxJava threading works. This code didn't want to run on another thread.
mAPIInterface.getAllProjects(accessToken)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Project>>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
mView.showLoadProgress();
}
#Override
public void onNext(#NonNull List<Project> allProjects) {
projects = allProjects;
mView.hideLoadProgress();
mView.onProjectsLoaded();
}
#Override
public void onError(#NonNull Throwable e) {
mView.hideLoadProgress();
mView.onProjectsLoadError();
}
#Override
public void onComplete() {
}
});
Then I have find the solution but I'm still not sure if it's ok. That's look like there are some more good solution:
mAPIInterface.getAllProjects(accessToken)
.subscribeOn(Schedulers.newThread())
.map(new Function<List<Project>, List<Project>>() {
#Override
public List<Project> apply(#NonNull List<Project> projects) throws Exception {
return projects;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Project>>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
mView.showLoadProgress();
}
#Override
public void onNext(#NonNull List<Project> allProjects) {
projects = allProjects;
mView.hideLoadProgress();
mView.onProjectsLoaded();
}
#Override
public void onError(#NonNull Throwable e) {
mView.hideLoadProgress();
mView.onProjectsLoadError();
}
#Override
public void onComplete() {
}
});
With that map() middleware it works. But should I use that everytime when I need to run the process on another thread?
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've an Observable something like this:
#GET("endpoint")
Observable<Something> getSomething();
and Subscriber like this
Subscriber<Something> somethingSubscriber = new Subscriber<Something>() {
public void onCompleted() {
}
public void onError(Throwable e) {
//handle exceptions
}
public void onNext() {
//do something
}
In my OnClickListener associated with a button, i make a subscription
getSomething()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(somethingSubscriber);
If i don't have an internet connection, onError is called and i do some exception handling. when I press the button again (assume i want to retry), the callback methods do not get called.
I want that onNext / onError callbacks get called everytime I press the button.
There is extention for RxJava. It has a lot of "cool tools", but for handling retrofit errors you can use ResponseOrError class.
So in you case it would looks like:
final PublishSubject<Object> clickSubject = PublishSubject.create();
final Observable<ResponseOrError<Something>> responseOrErrorObservable = clickSubject
.flatMap(new Func1<Object, Observable<ResponseOrError<Something>>>() {
#Override
public Observable<ResponseOrError<Something>> call(Object o) {
return getSomething()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.compose(ResponseOrError.<Something>toResponseOrErrorObservable());
}
})
.replay(1)
.refCount();
final Observable<Throwable> error = responseOrErrorObservable
.compose(ResponseOrError.<Something>onlyError())
.subscribe(new Action1<Segment>() {
#Override
public void call(Throwable throwable) {
// what to do on error, some toast or what ever yu need
}
});
final Observable<UserInfoResponse> success = responseOrErrorObservable
.compose(ResponseOrError.<Something>onlySuccess())
.subscribe(new Action1<Something>() {
#Override
public void call(Something some) {
// code what to do on success
}
});
And now, into onClick you just need to put clickSubject.onNext(null)
.replay(1).refCount(); needed because there are 2 Observables that uses responseOrErrorObservable, so without it retrofit request will "happens" two times.
You are reusing the same Subscriber. Once you get the onError or a result (so it completes) the subscriber is unsubscribed. Try to pass every time a new subscriber.
use this code
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getSomething()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Something>() {
#Override
public void call(Something something) {
//do something
}
},
new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
//handle exceptions
}
},
new Action0() {
#Override
public void call() {
}
});
}
});
Addition
or
replace this
Subscriber<Something> somethingSubscriber = new Subscriber<Something>() {
public void onCompleted() {
}
public void onError(Throwable e) {
//handle exceptions
}
public void onNext() {
//do something
}
};
to
Subscriber<String> somethingSubscriber = new Subscriber<String>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String s) {
}
};
In my Case onNext() and onError() methods are not getting called because of my model class wrong parsing, I was taking a double object as Integer so NumberFormatException was thrown and nothing was happening after getting the result from retrofit.