CoroutineScope中调用RecyclerView的notifyDataSetChanged致App崩溃
RecyclerView更新崩溃问题解决方案
核心问题很明确:Android所有UI操作必须在主线程执行,你在Dispatchers.IO子线程里调用adapter.notifyDataSetChanged(),直接违反了Android的线程规则,导致App崩溃。
解决方法:切换到主线程更新UI
在协程中,用withContext(Dispatchers.Main)将UI更新逻辑切回主线程即可,修改后的代码示例如下:
// 获取Firebase Token后发起请求 CoroutineScope(Dispatchers.IO).launch { try { // 网络请求获取数据 val response = apiService.getData(token) if (response.isSuccessful) { val dataList = response.body() ?: emptyList() // 将数据添加到集合 yourDataCollection.addAll(dataList) // 切换到主线程更新RecyclerView withContext(Dispatchers.Main) { adapter.notifyDataSetChanged() } } } catch (e: Exception) { // 处理请求异常,若要提示用户也需切到主线程 withContext(Dispatchers.Main) { Toast.makeText(context, "请求失败:${e.message}", Toast.LENGTH_SHORT).show() } } }
针对Kotlin新手的额外建议
- 优先使用
viewModelScope代替自定义的CoroutineScope(Dispatchers.IO),它会自动和页面生命周期绑定,避免内存泄漏:// 在ViewModel中使用 viewModelScope.launch(Dispatchers.IO) { // 网络请求逻辑... withContext(Dispatchers.Main) { adapter.notifyDataSetChanged() } } - 所有UI相关操作(包括更新Adapter、修改View属性等)都必须放在主线程,绝不可以在子线程执行。
- 如果想提升更新效率,可以用
notifyItemRangeInserted(startPosition, itemCount)代替notifyDataSetChanged(),只更新新增的数据项,避免全量刷新。
内容的提问来源于stack exchange,提问作者Pavrogold
相关产品推荐
相关产品推荐

