Are there any clear and smart solution to dispose observable from its subscribe method?
E.g. I have an Observable.interval that emits Long every second. In my subscribe method i want to check if 20 seconds gone than dismiss subscription.
val observable = Observable.interval(1000,TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ num ->
if(num == 20.toLong())
{
observable.dispose()//I cant call dispose here because variable 'observable' is not avaliable yet
}
})
What is the easiest and right way to achieve this logic?
I found one simple solution. Just divide variable declaration and initialization in to two steps.
E.g.
var observable:Disposable? = null
observable = Observable.interval(1000,TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ num ->
if(num == 20.toLong())
{
observable?.dispose()
}
})
Related
I have a network call I make as part of a function that fetches the timer value for how long this data is going to be alive (basically the ttl of an object). I need to retrigger the same function as soon as the timer ends.
fun refresh() {
service.makeNetworkCall()
.subscribe { response ->
val ttl = response.ttl
retriggerAgainAfterTtlExpires(ttl)
}
I'm currently retriggering the function in the .doOnNext() call as shown below. But this doesn't chain the observable to the original one. It creates a whole new process and I want to avoid it.
fun retriggerAgainAfterTtlExpires(ttl:Long) {
Observable.interval(ttl, ttl, TimeUnit.SECONDS)
.doOnNext { refresh() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
How can I retrigger this function without having to call .doOnNext()
Save the TTL in a field and use deferred creation of the initial delay. At the end, simply use repeat.
private long ttl = 1000 // initial TTL
Observable.defer(() -> {
return Observable.just(ttl).delay(ttl, TimeUnit.MILLISECONDS);
})
.flatMap(v -> service.networkCall())
.doOnNext(response -> { ttl = response.ttl; })
.observeOn(mainThread())
// handle other aspects of response
.repeat()
.subscribe(/* ... */);
For example we have a call:
getObsevable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::onSuccess, ::onError))
Is there is a way to not launch it if condition is true? For example:
getObsevable()
.stop({ Calendar.getInstance().get(Calendar.MINUTE) % 2 == 0 })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::onSuccess, ::onError))
In this code I mean we should not launch observable if current minute is odd. And launch it if current minute is even.
Yes, you can use filter to achieve this. So what happens when filter is used, if the condition doesn't meet, the stream below doesn't get executed.
In your case (or example), if the current minute is odd, the subscribe method wont be called. However, if it's even, the stream will work just the way it's written.
getObservable()
.filter({ Calendar.getInstance().get(Calendar.MINUTE) % 2 == 0 })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::onSuccess, ::onError))
You can read about it here -> http://reactivex.io/documentation/operators/filter.html
Assign it to a disposable, and dispose it before start another call, or wherever you need to dispose it
Disposable disposable;
public void createDisposableWithMyObservable(){
if(disposable != null) disposable.dispose();
disposable = getObsevable()
.stop({ Calendar.getInstance().get(Calendar.MINUTE) % 2 == 0 })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::onSuccess, ::onError));
}
I'm using rxJava and I want to do a forEach of a list, and for every item, make a call, and then once those calls are finished, call another one.
This is my code
val flowableList = answerListCreated.map {
questionService.addAnswerToQuestion(
questionId,
it.id,
MyUtils.getAccessTokenFromLocalStorage(context = mContext!!)
)
}
disposable = Flowable.concat(flowableList)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
addCorrectsAnswersToQuestion(questionId)
}
But it's joining in the subscribe twice, and it should join in the subscribe once.
What I'm missing? I thought concat should be a good option because I've read that it does first the first job, and then when job1 is finished it starts the job2.
Well, also if necessary I can return Observable<T>, from now in my service I'm returning Flowable<T> to test this.
i think you need to do something like:
val disposable = Flowable.fromArray(answerListCreated)
.flatMap {
questionService.addAnswerToQuestion(
questionId,
it.id,
MyUtils.getAccessTokenFromLocalStorage(context = mContext!!)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
.toList()
.subscribe {
addCorrectsAnswersToQuestion(questionId)
}
I am trying to learn RxJava2, and converting my AsyncTasks to Observables.
I have the following piece of code that I am trying to convert.
if(asyncTask.getStatus() == AsyncTask.Status.RUNNING){
asyncTask.cancel();
}
asyncTask = new CustomTask();
asyncTask.execute(input);
I tried to recreate the following with Disposables.
Disposable currentTask;
PublishSubject input = PublishSubject.create();
For every input
if(currentTask != null) currentTask.dispose();
currentTask = input
.map(// Network calls
// returns CustomObject)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
// do work with result
}, throwable -> Log.e(TAG, throwable.toString()));
However, currentTask is always null. Why? Is this the wrong way to do it??
You're using Disposable correctly but I can only assume you're messing up somewhere with the subject. Subjects in rx can be both publishers and subscribers... and subjects don't necessarily wait until subscribe(...) to start emitting items. For that reason, I wouldn't suggest replacing your AsyncTasks with any kind of Subject.
You can get similar, more deterministic behavior, doing this though:
Observable<CustomObject> networkObservable =
Observable.create(emitter ->
{
try {
CustomObject object = doNetworking();
emitter.onNext(object);
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
}
);
if(currentTask != null) currentTask.dispose();
currentTask = networkObservable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
// this next subscribe is similar to AsyncTask.execute() as it starts the stream
.subscribe(result -> {
// do work with result
}, throwable -> Log.e(TAG, throwable.toString()));
Also, consider looking into SerialDisposable and you don't have to do those null/dispose checks
SerialDisposable serialDisposable = new SerialDisposable();
Atomically: set the next disposable on this container and dispose the previous one (if any) or dispose next if the container has been disposed.
Disposable disposable = networkObservable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...);
serialDisposable.set(disposable); // this will call dispose on the previous task if it exists
Here's a simplified version of what I'm trying to do (using Kotlin and RxJava)
makeServerCall()
.doOnNext {
doStuff(it)
}
//TODO: if it == 0, call asyncOperation() and wait for its callback to fire
//before running the rest of the stream. Otherwise immediately run the rest
//of the stream
.flatMap {
observable1(it)
observable2(it)
Observable.merge(
getSpotSearchObservable(observable1),
getSpotSearchObservable(observable2)
}
.subscribeBy(onNext = {
allDone()
view?
})
How do I squeeze in the call to asyncOperation() and make the rest of the stream wait for its callback to fire, but only when a certain condition is met? This seems like it's probably a trivial operation in Rx, but no obvious solution is coming to mind.
FlatMap it!
.flatMap {
if (it == 0) {
return#flatMap asyncOperation()
.ignoreElements()
.andThen(Observable.just(0))
}
return#flatMap Observable.just(it)
}
.flatMap {
observable1(it)
observable2(it)
Observable.merge(
getSpotSearchObservable(observable1),
getSpotSearchObservable(observable2)
)
}