Activity类出现ConcurrentModificationException错误:Observer及foreach循环异常
报错原因
- 首先是代码逻辑错误:
setmMovies方法被放在了foreach循环内部,每遍历一条数据就会调用一次设置数据集的操作。如果setmMovies内部对传入的moviesDatas集合做了clear、add、remove等修改集合结构的操作,会直接导致正在运行的迭代器检测到集合版本变化,抛出ConcurrentModificationException,即使没有多线程操作也会触发该错误。 - 核心多线程冲突:ViewModel返回的
moviesDatas是可变集合实例,可能存在后台线程更新该集合、同时主线程遍历该集合的场景,多线程操作同一个可变集合就会触发并发修改异常。
修复代码
直接修改Observer回调内的逻辑,先创建集合副本再操作,同时把数据集设置操作移到循环外:
private void ObserveAnyChange() { moviesListViewModel.getMovies().observe(this, new Observer<List<MoviesData>>() { @Override public void onChanged(List<MoviesData> moviesDatas) { if(moviesDatas != null) { // 创建原集合的副本,后续所有操作都基于副本,不会影响原集合 List<MoviesData> safeMovies = new ArrayList<>(moviesDatas); for (MoviesData movies : safeMovies) { Log.v("Tag", "onChanged: " + movies.getTitle()); } // 数据集设置移到循环外部,传入副本避免后续操作冲突 movieRecyclerAdapter.setmMovies(safeMovies); } } }); }
可选优化建议
- Adapter内部更新数据集时配合
DiffUtil做增量更新,不要直接替换整个数据集,既提升列表滑动性能,也能减少集合修改概率。 - ViewModel层返回列表数据时,用
Collections.unmodifiableList()将集合包装为不可变集合返回,从源头上避免外部修改原集合引发的并发问题。
内容的提问来源于stack exchange,提问作者Arya_94
相关产品推荐
相关产品推荐

