android - android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触其视图。(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());
}
}));
如您所见,我提供了 AndroidSchedulers.mainThread() 来订阅。我正在获取 onSucces 方法的数据,但 recyclerview 适配器没有在 UI 上更新它。
让我告诉你最棘手的部分:如果我通过锁定屏幕或按下主页按钮将应用程序切换到前台并返回应用程序,我的 UI 会使用我收到的数据进行更新。
解决方案
你应该使用observeOn(AndroidSchedulers.mainThread())
not subscribeOn(AndroidSchedulers.mainThread())
。用于
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
subscribeOn用于指定 Observable 将在其上运行的调度程序。在您的情况下,它将是一个 IO 调度程序。
ObserveOn用于指定观察者将在其上观察此 Observable 的调度程序,即在这种情况下完成将是主线程
推荐阅读
- flutter - Dart,Flutter : const 修饰符的含义,Colors.yellow [200] 不是常量吗?
- php - 如何验证 PayPal 订阅
- go - 如何在golang中的JSON类型中插入空值
- ffmpeg - 视频片段的两个ffmpeg命令的比较
- python - 散点图:获取 ValueError(x 和 y 必须相同大小)
- python - 在数据框中查找具有特定字符串值的连续行?
- python - Python Module CSV 在 CSV 文件的 writen 行之间添加一个空行
- python - 在 python 中创建带有正则表达式错误的 if/elif 语句
- javascript - 我得到了 base64 [目标文件],如何将其转换为正确的 base64 文件?
- reactjs - 无法在渲染中调用函数