How to delay loading items by using RxJava? - android

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

Related

How to call manually onNext method in RxJava?

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()
}

RXJava Observable executing on main thread instead of background thread

I created an Observable using the Observable.fromCallable method and subscribed to it as shown in the code snippet below.
Observable<String> stringObservable = Observable.fromCallable(new Callable<String>() {
#Override
public String call() throws Exception {
Thread.sleep(1000);
return Thread.currentThread().getName();
}
});
stringObservable.subscribeOn(Schedulers.io());
stringObservable.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String aDouble) {
Toast.makeText(SimpleActivity.this, "onNext: " + aDouble,
Toast.LENGTH_LONG).show();
}
#Override
public void onError(Throwable e) {
new AlertDialog.Builder(SimpleActivity.this)
.setTitle("Error")
.setMessage(e.toString())
.show();
}
#Override
public void onComplete() {
}
});
The snippet above produced a toast showing that the Callable was run on the main thread instead of the Schedulers.io thread. What's happening?
Every operation on an Observable creates a new instance and does not effect the original one. Therefore
stringObservable.subscribeOn(Schedulers.io());
does not affect your code below.
The correct way of using them would be in a chain instead of using a variable.
Observable.fromCallable(new Callable<String>() {
#Override
public String call() throws Exception {
Thread.sleep(1000);
return Thread.currentThread().getName();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String aDouble) {
Toast.makeText(SimpleActivity.this, "onNext: " + aDouble,
Toast.LENGTH_LONG).show();
}
#Override
public void onError(Throwable e) {
new AlertDialog.Builder(SimpleActivity.this)
.setTitle("Error")
.setMessage(e.toString())
.show();
}
#Override
public void onComplete() {
}
});

RxJava Android threading boilerplate

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?

RxAndroid interval API call. Is there a better way?

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);
}
});

Retry only failed observable RxJava 2

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() {
}
});

Categories

Resources