5

我在更改主屏幕墙纸的 IO 线程上有简单的工作,之后我尝试在 UI 线程上运行一些动画:

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

但这种方法会导致错误: java.lang.IllegalStateException: Observers must subscribe from the main UI thread, but was Thread[RxCachedThreadScheduler-1,5,main]

我试图将第二个 Observable 更改为:

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

但这没有帮助。

4

2 回答 2

10

AppObservable.bindFragment(this, Observable.just(0))抛出异常,因为它不是从主线程调用的

此代码未在主线程中调用,因为您Schedulers.io在此代码中观察到(见下文),而不是后者调用AppObservable.bindFragment(this, Observable.just(0))

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

您想在 io 线程中执行任务,然后在主线程中执行任务。为此,您可以使用 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());

请注意,我使用defer将您的异步任务表示为 an,Observable但您可以将flatMap调用替换为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());
于 2015-05-13T14:49:40.443 回答
5

实际上,observeOn 用于订阅者线程,而 subscribeOn 用于可观察线程。所以你应该扭转它们

.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
于 2015-05-13T10:08:07.763 回答