RxAndroid: UI changes on Schedulers.io() thread

人盡茶涼 提交于 2019-12-06 03:14:02

问题


I have simple job on IO thread which is changing home screen wallpaper, after that I'm trying to run some animation on 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 error: java.lang.IllegalStateException: Observers must subscribe from the main UI thread, but was Thread[RxCachedThreadScheduler-1,5,main]

I've tried to change second Observable to:

  AppObservable.bindFragment(this, Observable.just(0))
    .delay(2000, TimeUnit.MILLISECONDS)
    .observeOn(Schedulers.io())
    .subscribeOn(AndroidSchedulers.mainThread())
    .subscribe(integer -> loadFinishAnimationAfterSetWallpaper());

But it didn't help.


回答1:


AppObservable.bindFragment(this, Observable.just(0)) throw an exception as it's not called from the Main Thread

This code is not called in the main thread because you observe on Schedulers.io in this code (see bellow), than latter call AppObservable.bindFragment(this, Observable.just(0))

AppObservable.bindFragment(this, Observable.just(0))
   .observeOn(Schedulers.io())
   .subscribe(v -> setWallpaperOnSeparateThread());

You want to perform a task in io thread, then perform a task in main thread. To do so, you can chain you 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 use defer to represente you async task as an Observable but you can replace the flatMap call with doOnNext call.

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());



回答2:


Actually observeOn is for the subcscriber thread while subscribeOn is for observable thread. So you should reverse them

.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())


来源:https://stackoverflow.com/questions/30211397/rxandroid-ui-changes-on-schedulers-io-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!