【问题标题】:Access to items layout from RxAndroid?从 RxAndroid 访问项目布局?
【发布时间】:2018-06-12 14:27:36
【问题描述】:

我正在使用下面的代码:

    mCompositeDisposable.add(myObservable(IdLang, shortTermCoursesModels)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableObserver<String>() {
                @Override
                public void onComplete() {
                }

                @Override
                public void onError(Throwable e) {
                }

                @Override
                public void onNext(String string) {
                    listenerCoursesListItemService.adapterHideProgress();
                }
            }));

还有:

private Observable<String> myObservable(String IdLang, List<GetShortTermCoursesModel> shortTermCoursesModels) {
    return Observable.defer(new Callable<ObservableSource<? extends String>>() {
        @Override
        public ObservableSource<? extends String> call() throws Exception {
            listenerCoursesListItemService.adapterShowProgress();
            for (int i = 0; i < 900000; i++) {
                Log.i("WWWWWWWW", "A " + i);
            }
            return Observable.just("ok");
        }
    });

但请告诉我以下错误:

 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

如何从RxAndroid 访问UI

我的错误在这里:

listenerCoursesListItemService.adapterShowProgress();
listenerCoursesListItemService.adapterHideProgress();

【问题讨论】:

  • 你如何将你的视图请求传递给你的 Observable?您是否使用任何 Android 架构 MVP、MVVM、VIPER?
  • 我正在使用 mvp。

标签: android android-layout rx-java rx-android android-mvp


【解决方案1】:

原因是你试图显示进度 ->

listenerCoursesListItemService.adapterShowProgress(); 

实际上在不同线程 (Schedulers.io()) 而不是 UI 线程 (AndroidSchedulers.mainThread()) 上运行的 call() 方法。

相反,您可以在 doOnSubscribe() 方法中显示进度,并在 onComplete() 中将其关闭。这两种方法都将在 UI 线程上调用。更新了下面的代码以供参考,

mCompositeDisposable.add(myObservable(IdLang, shortTermCoursesModels)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnSubscribe(new Consumer<Disposable>() {
        @Override
        public void accept(@NonNull Disposable disposable) throws Exception {
            listenerCoursesListItemService.adapterShowProgress();
        }
    })
    .doFinally(new Action() {
        @Override
        public void run() throws Exception {
           listenerCoursesListItemService.adapterHideProgress();
        }
    })
    .subscribeWith(new DisposableObserver<String>() {
        @Override
        public void onComplete() {
        }

        @Override
        public void onError(Throwable e) {
        }

        @Override
        public void onNext(String string) {
        }
    }));

还有:

private Observable<String> myObservable(String IdLang, List<GetShortTermCoursesModel> shortTermCoursesModels) {
    return Observable.defer(new Callable<ObservableSource<? extends String>>() {
        @Override
        public ObservableSource<? extends String> call() throws Exception {
            for (int i = 0; i < 900000000; i++) {
                Log.i("WWWWWWWW", "A " + i);
            }
            return Observable.just("ok");
        }
    });
}

在 onNext() 中你会得到你从 call() 方法返回的字符串。

【讨论】:

    【解决方案2】:

    你必须订阅主线程:

    mCompositeDisposable.add(myObservable(IdLang, shortTermCoursesModels)
            .subscribeOn(AndroidSchedulers.mainThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableObserver<String>() {
                @Override
                public void onComplete() {
                }
    
                @Override
                public void onError(Throwable e) {
                }
    
                @Override
                public void onNext(String string) {
                    listenerCoursesListItemService.adapterHideProgress();
                }
            }));
    

    【讨论】:

    • 您的答案会起作用,但是,这没有意义,因为所有工作负载都将在 UI 线程上完成。所有工作都必须在不同的线程上完成,一旦完成就返回调用线程(在本例中为 AndroidSchedulers.mainThread())。这就是 Rx 的美妙之处 :)。在线程之间轻松切换。
    • 是的,你是对的!也许访问ui的代码应该被隔离,然后使用主线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多