I'm new to rxjava 2 and i'm trying to execute someMethod in the background with a given interval and use the result on the UI thread. Can someone point me where i made mistake in my code or even better provide optimal code that does the job i need?
#Override
protected void onStop() {
subject.onNext(Long.valueOf(10005));
observable.unsubscribeOn(Schedulers.io());
super.onStop();
}
private void initAzimuthUpdater() {
subject = PublishSubject.create();
observable = Observable.interval(500, TimeUnit.MILLISECONDS)
.takeWhile(new Predicate<Long>() {
#Override
public boolean test(#NonNull Long aLong) throws Exception {
Log.d(TAG, "xxxxxxxxxxxx test: " + aLong);
return aLong != Long.valueOf(10005);
}
});
observable.flatMap(new Function<Long, ObservableSource<Float>>() {
#Override
public ObservableSource<Float> apply(#NonNull Long aLong) throws Exception {
return PublishSubject.create(new ObservableOnSubscribe<Float>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Float> e) throws Exception {
e.onNext(someMethod());
}
});
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Float>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
Log.d(TAG, "xxxxxxxx onSubscribe:" + System.currentTimeMillis());
isRunning = true;
}
#Override
public void onNext(#NonNull Float o) {
Log.d(TAG, "xxxxxxxx onNext:" + System.currentTimeMillis());
//update UI
}
#Override
public void onError(#NonNull Throwable e) {
Log.d(TAG, "xxxxxxxx onError:" + System.currentTimeMillis());
}
#Override
public void onComplete() {
Log.d(TAG, "xxxxxxxx onComplete:" + System.currentTimeMillis());
}
});
subject.mergeWith(azimuthObservable);
}
You should use DisposableObserver and subscribeWith, save the Disposable into a CompositeDisposable, then call clear() on it from onStop(). The Observable operators return a new instance so ignoring their return value will have no effect on the original flow.
CompositeDisposable composite = new CompositeDisposable();
#Override
protected void onStop() {
composite.clear();
super.onStop();
}
private void initAzimuthUpdater() {
Disposable d = Observable.interval(500, TimeUnit.MILLISECONDS)
.flatMap(new Function<Long, ObservableSource<Float>>() {
#Override
public ObservableSource<Float> apply(#NonNull Long aLong)
throws Exception {
return Observable.create(new ObservableOnSubscribe<Float>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Float> e)
throws Exception {
e.onNext(someMethod());
}
});
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<Float>() {
#Override
public void onStart() {
Log.d(TAG, "xxxxxxxx onSubscribe:" + System.currentTimeMillis());
isRunning = true;
}
#Override
public void onNext(#NonNull Float o) {
Log.d(TAG, "xxxxxxxx onNext:" + System.currentTimeMillis());
//update UI
}
#Override
public void onError(#NonNull Throwable e) {
Log.d(TAG, "xxxxxxxx onError:" + System.currentTimeMillis());
}
#Override
public void onComplete() {
Log.d(TAG, "xxxxxxxx onComplete:" + System.currentTimeMillis());
}
});
composite.add(d);
}
Related
I'm testing RxJava at the moment, and I get confused.
I placed method with Thread.sleep(5000)
into Schedulers.io()
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(longOperation()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
customToast("long operation done");
}
#Override
public void onError(Throwable e) {
}
}));
I read, we should move long operation into schedulers.io because we can't freeze UI thread, but in this case, I got freeze UI. What is wrong ?
longOperation() have Thread.sleep(5000) inside.
//after edit Callable
private void doSomething() throws InterruptedException {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(Observable.fromCallable(()-> longOperation())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
customToast("long operation done");
}
#Override
public void onError(Throwable e) {
}
}));
}
private Completable longOperation() throws InterruptedException {
Thread.sleep(5000);
return Completable.complete();
}
You should be using defer() so that it actually executes on the scheduler instead of when you're trying to create the completable.
private void doSomething() throws InterruptedException {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(Completable.defer(new Callable<CompletableSource>() {
#Override
public CompletableSource call() throws Exception {
return longOperation();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
customToast("long operation done");
}
#Override
public void onError(Throwable e) {
}
}));
}
private Completable longOperation() throws InterruptedException {
Thread.sleep(5000);
return Completable.complete();
}
What is the correct way to implement the tests below using rxjava2?
Given a list of ntp servers, test each one until you succeed.
Example:
time.nist.gov -> timeout
pool.ntp.org -> timeout
time.google.com -> success, get date
time.apple.com -> ignore
I do not want to test all in parallels but one by one. And if all fail, it restarts the test again.
Using only one server, the code I'm using is this:
public void getTime() {
timeObservable = Observable
.fromCallable(new Callable<Date>() {
#Override
public Date call() throws IOException {
return connectAndGetTime(HOST);
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new Consumer<Throwable>() {
#Override
public void accept(Throwable error) {
Timber.tag(TAG).e(error);
}
})
.retry(5);
timeObservable.subscribe(new Consumer<Date>() {
#Override
public void accept(Date date) {
mDate = date;
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) {
Timber.tag(TAG).e(throwable);
}
});
}
Thanks!
Thanks Alexei, you're right.
Why complicate things?
The end result looks like this:
public void getTime() {
timeObservable = Observable
.fromCallable(new Callable<Date>() {
#Override
public Date call() {
for (String host : Arrays.asList("time.google.com", "time.apple.com", "time.nist.gov")) {
try {
return connectAndGetTime(host);
} catch (Exception e) {
Timber.tag(TAG).d("Sync (%s) fail!", host);
}
}
return null;
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(new Consumer<Throwable>() {
#Override
public void accept(Throwable error) {
Timber.tag(TAG).e(error);
}
})
.retry(5);
timeObservable.subscribe(new Consumer<Date>() {
#Override
public void accept(Date date) {
mDate = date;
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) {
Timber.tag(TAG).e(throwable);
}
});
}
As shown in the following code, I would like to use RxAndroid. but when i run the code, i dont receive any logs from
#Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
please let me know hopw to fix these issue.
code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Observer<String> animalsObserver = getAnimalsObserver();
getAnimalsObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter(new Func1<String, Boolean>() {
#Override
public Boolean call(String s) {
return s.toUpperCase().equals("D");
}
})
.subscribe(animalsObserver);
}
private Observable getAnimalsObservable() {
return Observable.from(Arrays.asList(
new String[] {
"Ant", "Ape",
"Bat", "Bee", "Bear", "Butterfly",
"Cat", "Crab", "Cod",
"Dog", "Dove",
"Fox", "Frog"
}
));
}
private Observer<String> getAnimalsObserver() {
return new Observer<String>() {
#Override
public void onNext(String s) {
Log.d(TAG, "Name: " + s);
}
#Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
#Override
public void onCompleted() {
Log.d(TAG, "All items are emitted!");
}
};
}
}
return s.toUpperCase().equals("D");
this is always false. You might want to check with startsWith. You can read more here
I am trying to make webservie call using retrofit and rxjava 2. i was exploring two different approach to use RxJava2. problem is i am getting response whene i use Observable but it is not working with Flowable. Logs are not getting printed when using Flowable i tried to debug it but its not going inside onNext or onComplete or onError. only onSubscribe gets executed.
1) using observable as return type
new WebRequestManager().getContactObservable(userRequest)
.subscribe(new Observer<ResponseData>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(ResponseData responseData) {
Log.e(TAG , "data "+responseData.getStatus());
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
Log.e(TAG , "data complete");
}
}
);
2) Using flowable as return type
new WebRequestManager().getContactFlowable(userRequest)
.subscribe(new Subscriber<ResponseData>() {
#Override
public void onSubscribe(Subscription s) {
Log.e(TAG , "contact subscription ");
}
#Override
public void onNext(ResponseData responses) {
Log.e(TAG , "contact onNext ");
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
Log.e(TAG , "contact onComplete ");
}
});
Rest contact retrofit api
public interface ContactApi {
#POST(WebRequest.GET_CONTACTS)
Flowable<ResponseData> getContactFlowable(#Body UserRequest userRequest);
#POST(WebRequest.GET_CONTACTS)
Observable<ResponseData> getContactObservable(#Body UserRequest userRequest);
}
call to webservice
public Flowable<ResponseData> getContactsData(UserRequest userRequest){
return webRequest.getWebClient().create(ContactApi.class).getContacts(userRequest);
}
public Observable<ResponseData> getContact(UserRequest userRequest){
return webRequest.getWebClient().create(ContactApi.class).getContact(userRequest);
}
getting retrofit instance
public static Retrofit getWebClient(){
//if(okHttpClient == null)
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(120,TimeUnit.SECONDS)
.readTimeout(120,TimeUnit.SECONDS)
.writeTimeout(120,TimeUnit.SECONDS)
.addInterceptor(new WebRequestInterceptor("\"application/json\""))
.build();
// if(client == null)
client = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(LoganSquareConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return client;
}
With Subscribers, you have to call request to get items:
new WebRequestManager().getContactFlowable(userRequest)
.subscribe(new Subscriber<ResponseData>() {
#Override
public void onSubscribe(Subscription s) {
Log.e(TAG , "contact subscription ");
s.request(Long.MAX_VALUE); // <---------------------------------
}
#Override
public void onNext(ResponseData responses) {
Log.e(TAG , "contact onNext ");
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
Log.e(TAG , "contact onComplete ");
}
});
See also DisposableSubscriber with its example.
Android how to check the unit test with powermockito
public void updateProfile(final UserLogin updateUser) {
profileModelImple.updateUser(updateUser)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Object>() {
#Override
public void onCompleted () {
}
#Override
public void onError (Throwable e) {
Timber.e("authenticationModel -> login " + e);
EventBus.getDefault().post(null);
}
#Override
public void onNext (Object user) {
}
});
}