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);
}
});
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>).
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() ....
}
I use retrofit2 in my project. I have interface:
public interface ProductService {
#POST("findProducts")
Observable<ProductsResponse> getProducts();
}
and service method:
public ProductService getProductService() {
return getService(ProductService.class);
}
After that I use this service in my fragment. When I click to button I call this method:
#Override
public void onClick(View view) {
if (view.getId() == R.id.button) {
RestApiFactory.getInstance().getProductService().getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new ProductHandler());
}
}
and realise handler in this fragment:
private class ProductHandler implements Observer<ProductsResponse> {
#Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: start");
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void onNext(ProductsResponse value) {
//save to DB in new Thread
}
#Override
public void onError(Throwable e) {
Log.d(TAG, "onError: "+ e.getMessage());
price.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.INVISIBLE);
}
#Override
public void onComplete() {
Log.d(TAG, "onComplete: finish");
price.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.INVISIBLE);
}
}
is it correct to implement ProductHandler implements Observer<ProductsResponse>'s methods
onSubscribe
onNext
onError
onComplete
in fragment?
I'm advised to move this in a singleton:
MySingleton.getInstanse().getData();
and move all to getData :
public void getData(){
RestApiFactory.getInstance().getProductService().getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ProductsResponse>() {
#Override
public void onSubscribe(Disposable d) {
//send broadcast and catch in Fragment
}
#Override
public void onNext(ProductsResponse productsResponse) {
//send broadcast and catch in Fragment
}
#Override
public void onError(Throwable e) {
//send broadcast and catch in Fragment
}
#Override
public void onComplete() {
//send broadcast and catch in Fragment
}
});
}
but I think this is nonsense. who will tell you how to use it (in what place) Observable from retrofit?
there is no need to implement Observer.You can just need to create an observer for the same.Let's see the example.
service.getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(mObserver);
}
the observer should look like and must be initialized in oncreate:
mObserver = new Observer<ProductsResponse>() {
#Override
public void onSubscribe(Disposable d) {
mDisposableList.add(d);
}
#Override
public void onNext(ProductsResponse value) {
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onComplete() {
}
};
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() {
}
});