RxAndroid: UI changes in Schedulers.io () thread
I have a simple work on an I / O thread that changes the desktop wallpaper, after which I try to run an animation on the UI thread:
AppObservable.bindFragment(this, Observable.just(0))
.observeOn(Schedulers.io())
.subscribe(v -> setWallpaperOnSeparateThread());
private void setWallpaperOnSeparateThread() {
WallpaperHelper.setBitmapAsWallpaper(photoViewAttacher.getVisibleRectangleBitmap(), getBaseActivity());
AppObservable.bindFragment(this, Observable.just(0))
.delay(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(integer -> loadFinishAnimationAfterSetWallpaper());
}
but this approach results in an error:
java.lang.IllegalStateException: Observers must subscribe from the main UI thread, but was Thread[RxCachedThreadScheduler-1,5,main]
I tried to change the second Observable to:
AppObservable.bindFragment(this, Observable.just(0))
.delay(2000, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(integer -> loadFinishAnimationAfterSetWallpaper());
But it did not help.
source to share
AppObservable.bindFragment(this, Observable.just(0))
throws an exception as it is not called from the main thread
This code is not called on the main thread, because you observe Schedulers.io
in this code (see below) than the last callAppObservable.bindFragment(this, Observable.just(0))
AppObservable.bindFragment(this, Observable.just(0))
.observeOn(Schedulers.io())
.subscribe(v -> setWallpaperOnSeparateThread());
You want to execute a task on the io thread and then execute the task on the main thread. To do this, you can link the call using one Observable
.
AppObservable.bindFragment(this, Observable.just(0))
.observeOn(Schedulers.io())
.flatMap(v -> Observable.defer(() -> WallpaperHelper.setBitmapAsWallpaper(photoViewAttacher.getVisibleRectangleBitmap(), getBaseActivity())))
.delay(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(v -> loadFinishAnimationAfterSetWallpaper());
Please note, I am using defer
to represent your asynchronous task as Observable
, but you can replace call flatMap
with call doOnNext
.
AppObservable.bindFragment(this, Observable.just(0))
.observeOn(Schedulers.io())
.doOnNext(v -> WallpaperHelper.setBitmapAsWallpaper(photoViewAttacher.getVisibleRectangleBitmap(), getBaseActivity()))
.delay(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(v -> loadFinishAnimationAfterSetWallpaper());
source to share