I'm trying to emits objects from list with 1 sec interval.
AppObservable.bindFragment(this, Observable.from(actionButtonList))
.subscribeOn(Schedulers.newThread())
.flatMap(ab -> Observable.defer(() -> Observable.just(ab).delay(1000, TimeUnit.MILLISECONDS)))
.observeOn(AndroidSchedulers.mainThread())
.doOnEach(notification -> ObjectAnimator.ofFloat(notification.getValue(), "alpha", 1, 0).setDuration(500).start())
.subscribe(ab -> Log.d(TAG, ab.toString()));
With this approach doOnEach is executed at the same time. What am I doing wrong?
You can zip a timer with your list:
Observable
.timer(1, 1, TimeUnit.SECONDS).onBackpressureDrop()
.zipWith(actionButtonList, (t, b) -> b)
.subscribeOn(...)
.observeOn(...)
.doOnNext(...)
.subscribe(...)
Related
I am trying to download file with RxAndroid and Retrofit, I want my Observable can emit download status on processing.
My expectation:
Observable.create()
.emit(PENDING)
.emit(START)
.flatMap(() -> {
emit(DOWNLOADING);
return apiService.download();
})
.onSuccess(() -> {
emit(SUCCESS);
)
.onError(() -> {
emit(ERROR);
})
You can check the download status with the desired time interval and update the status:
getDownloadStatus()
.zipWith(Observable.interval(500, TimeUnit.MILLISECONDS), (status, interval) -> (String) status)
.repeat()
.distinctUntilChanged()
.doOnNext(status -> ...). //some other operators
Use
Observable.create (emitter -> {})
By emitter.emit(value)
you can do it. But remember free the observable when you've done the task
i try to get an array of flowable get executed in parallel with FlowableFromArray
and emit the FlowableFromArray when all flowables are done.
But I'm missing the method to emit on last/latest.
I could only manage to make it work to emit onNext #see below
val results = FlowableFromArray(flowableArray).parallel()
.runOn(Schedulers.io())
.sequential()
.zipWith(r, BiFunction { t1: Flowable<String>, t2: Int
->
t1
.subscribeOn(Schedulers.io())
.map { i -> parseYoutubeTrack(i) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { next -> TLog.i(TAG, "_NEXT_ ${next.videoId}") }
})
.subscribe()
I have simple job which is selecting data using GreenDao. Also i want show ProgressWheel, but this job blocks UI thread.
showLoader();
DataManager.getInstance(this).getQuestions(0, 800)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(QuestionUtils::shuffleAnswers)
.subscribe(this::onFinishLoad);
And
public Observable<List<Question>> getQuestions(int offset, int limit) {
return Observable.fromCallable(() -> daoSession.getQuestionDao().queryBuilder()
.offset(offset)
.limit(limit)
.build().list());
}
It blocks because of the order of your operations.
DataManager.getInstance(this)
.getQuestions(0, 800)
.map(QuestionUtils::shuffleAnswers)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onFinishLoad);
should solve it. Else you would subscribe data and map them after.
If you want to finish the loader onec your data are emitted you can use action in your subscribe method and process the loading in your emitted nextData.
.subscribe (nextData -> {}, error -> {}, () -> doCompletedStuff())
I'm trying to create an Observable such that it will load some data from the network on an interval, and whenever the user refreshes the page. This is the gist of what I have so far:
PublishSubject<Long> refreshSubject = PublishSubject.create();
Observable<MyDataType> observable = Observable.merge(
Observable.interval(0, 3, TimeUnit.SECONDS),
refreshSubject
)
.flatMap(t -> {
// network operations that eventually return a value
// these operations are not observables themselves
// they are fully blocking network operations
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
// update ui with data
}, error -> {
// do something with error
});
Later in a refresh callback I have:
refreshSubject.onNext(0L);
It runs on the interval fine, however when I refresh, it explodes with a NetworkOnMainThreadException. I thought that I handled this with subscribeOn/observeOn. What am I missing? Also, why doesn't this cause a crash when the Observer is triggered from the interval?
You have to change your subscribeOn(Schedulers.io()) to observeOn(Schedulers.io()) and move it over your flatMap.
The reason for this is that your refreshSubject is a PublishSubject, which is an Observable and an Observer.
Since the onNext() of this PublishSubject is called inside the intern Observable first before the result gets delivered to your subscription.
This is also the reason that it works when you just use your Observable(and the fact that interval always subscribes to the computation thread by default).
Just check the output of those two snippets:
Observable.merge(
Observable.interval(0, 3, TimeUnit.SECONDS),
refreshSubject
)
.observeOn(Schedulers.io())
.doOnNext(aLong -> Log.d("Thread", Thread.currentThread().toString()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
Log.d("Subscribe Thread", Thread.currentThread().toString());
}, error -> {
// do something with error
});
vs
Observable.merge(
Observable.interval(0, 3, TimeUnit.SECONDS),
refreshSubject
)
.doOnNext(aLong -> Log.d("Thread", Thread.currentThread().toString()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
Log.d("Subscribe Thread", Thread.currentThread().toString());
}, error -> {
// do something with error
});
I want emit items with a specified delay, repeatedly from an arraylist.
Observable.from(saverFileNameList)
.subscribeOn(AndroidSchedulers.mainThread())
.flatMap(urlString -> Observable.just(urlString)
.delay(5000, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(urlString1 -> {
...
})
).repeat()
.subscribe();
This is not working, for some reason, i have set a print log on onNext, and i can see everything is being printed very fast so the delay is not being applied. What am i doing wrong
If you want to delay the emission of the source by the given amount, you can use the following:
Observable.from(saverFileNameList)
.delay(5000, TimeUnit.MILLISECONDS)
.repeat()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(v -> { }, Throwable::printStackTrace);
If you want to have in-between delay, use the following:
Observable.from(saverFileNameList)
.zipWith(Observable.interval(5, SECONDS).onBackpressureBuffer(), (a, b) -> a)
.repeat()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(v -> { }, Throwable::printStackTrace);