android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触其视图。 (RxJava)

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

我发现很多关于我遇到的错误的文章,我知道我们只能从主线程更新 UI。让我告诉你我遇到的整个错误:

E/RxEroor: The exception could not be delivered to the consumer because it has already cancelled/disposed of the flow or the exception has nowhere to go, to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

我使用这个时遇到错误:

  RxJavaPlugins.setErrorHandler(throwable -> {
        Log.e("RxEroor",throwable.getLocalizedMessage());
    });

我正在使用 rxjava 从改造网络调用中观察事物。这是我从片段调用 ViewModel 以获取数据。

compositeDisposable.add(songsOfCategoryViewModel.getAllSongs(1)
            .subscribeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableSingleObserver<ServerResponse<JsonObject>>() {
                @Override
                public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull ServerResponse<JsonObject> jsonObjectServerResponse) {

                    if (jsonObjectServerResponse.isStatus()){
                        Log.i("Songs Of Category",jsonObjectServerResponse.getData().toString());
                        List<SongModel> serverSongList = new Gson()
                                .fromJson(jsonObjectServerResponse.getData().get("songs")
                                        .getAsJsonArray(),new TypeToken<List<SongModel>>(){}.getType());

                        localSongList.addAll(serverSongList);
                        songAdapter.notifyDataSetChanged();
                      /*  Observable
                                .fromIterable(serverSongList)
                                .observeOn(Schedulers.io())
                                .subscribeOn(AndroidSchedulers.mainThread())
                                .subscribe(new DisposableObserver<SongModel>() {
                                    @Override
                                    public void onNext(@io.reactivex.rxjava3.annotations.NonNull SongModel songModel) {
                                        Log.i("Song",songModel.getTitle());
                                        localSongList.add(songModel);
                                        songAdapter.notifyDataSetChanged();

                                    }

                                    @Override
                                    public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {

                                    }

                                    @Override
                                    public void onComplete() {
                                        Log.i("onComplete","Called");

                                    }
                                });
                        */

                    }else {
                        Log.e("Error",jsonObjectServerResponse.getMessage());
                    }
                }

                @Override
                public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
                    Log.e("Error",e.getMessage());

                }
            }));

如您所见,我已向 subscribeOn 提供 AndroidSchedulers.mainThread()。我在 onSucces 方法上获取数据,但 recyclerview 适配器未在 UI.

上更新它

让我告诉你最棘手的部分:如果我通过锁定屏幕或按主页按钮将应用程序切换到前台并 return 到应用程序,我的 UI 会更新为我收到的数据。

您应该使用 observeOn(AndroidSchedulers.mainThread()) 而不是 subscribeOn(AndroidSchedulers.mainThread()) 。用作

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

subscribeOn used to specify the Scheduler on which an Observable will operate. In your case it will be an IO scheduler.

ObserveOn is used specify the Scheduler on which an observer will observe this Observable i.e the completion in this case it will be Main thread