adapter刷新时需要在主线程之中记录

本文探讨了在Android应用中更新Adapter时必须确保操作在主线程进行的重要性。详细解析了一个具体的错误案例,即尝试在非主线程中调用Adapter的notifyDataSetChanged()方法导致的异常,强调了正确使用runOnUiThread方法来切换线程的必要性。

结论:adapter的notifychange需要在主线程之中,可以使用runonuithread方法切换线程

 

mpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6600)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:931)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.view.View.requestLayout(View.java:18745)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.widget.AbsListView.requestLayout(AbsListView.java:1975)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:840)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6256)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at com.kidswant.component.base.adapter.KWBaseAdapter.setData(KWBaseAdapter.java:70)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at com.kidswant.kidim.ui.ChatSessionFragment.resetAdapter(ChatSessionFragment.java:483)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at com.kidswant.kidim.ui.ChatSessionFragment.onUserInfoCallback(ChatSessionFragment.java:889)
01-08 20:29:18.785 27036 27225 E AndroidRuntime:     at com.kidswant.kidim.chat.UserInfoLoader.notifyObservers(UserInfoLoader.java:62)

在 Kotlin 中,适配器(Adapter)用于将数据绑定到 UI 组件(如 ListView 或 RecyclerView)。为了刷新列表中的数据并通知界面更新,通常有以下几种方法: ### 1. 使用 `notifyDataSetChanged()` 更新整个列表 这是最常见的方法之一,适用于需要完全重新绘制列表的情况。通过调用 Adapter 的 `notifyDataSetChanged()` 方法,可以通知 RecyclerView 或 ListView 数据已发生改变,并强制其重新渲染所有可见项目。 ```kotlin adapter.notifyDataSetChanged() ``` 这种方式虽然简单易用,但在大型数据集中可能会带来性能开销,因为它会重新测量和布局所有的子项[^1]。 --- ### 2. 局部刷新:使用 `notifyItemChanged()`, `notifyItemInserted()`, 和 `notifyItemRemoved()` 对于更精细的控制,RecyclerView 提供了一系列局部刷新的方法,允许开发者仅更新受影响的部分而不是整个列表。这些方法包括但不限于: - **`notifyItemChanged(position)`**: 表示某一项的数据发生了变化。 - **`notifyItemInserted(position)`**: 插入了一条新的数据项。 - **`notifyItemRemoved(position)`**: 删除了一个现有的数据项。 #### 示例代码: 假设我们有一个名为 `WordListAdapter` 的自定义 Adapter 类,它继承自 `RecyclerView.Adapter`: ```kotlin wordList.add("New Item") // 向数据源添加一条新记录 adapter.notifyItemInserted(wordList.size - 1) wordList.removeAt(indexToRemove) // 移除指定索引位置上的元素 adapter.notifyItemRemoved(indexToRemove) ``` 这种方法能够显著提高应用性能,尤其是在处理大数据量显得尤为重要[^2]。 --- ### 3. DiffUtil 计算数据差异并高效更新 Google 推荐使用 `DiffUtil` 工具类来计算新旧数据之间的区别,从而实现更加高效的列表更新策略。相比手动调用多个 notifyXxx 方法,`DiffUtil` 能够自动化这一流程,减少错误发生的可能性。 要使用 `DiffUtil` ,需先创建一个实现了 `DiffUtil.Callback` 接口的对象,再将其传递给 `DiffUtil.calculateDiff(callback)` 函数获取最终的结果回调实例。最后调用 `dispatchUpdatesTo(adapter)` 即可完成更新工作。 #### 示例代码: ```kotlin val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { override fun getOldListSize(): Int = oldData.size override fun getNewListSize(): Int = newData.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = oldData[oldItemPosition].id == newData[newItemPosition].id override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = oldData[oldItemPosition] == newData[newItemPosition] }) diffResult.dispatchUpdatesTo(adapter) ``` 这种做法不仅提高了用户体验流畅度,还降低了开发难度[^3]。 --- ### 4. 结合 Handler 进行异步线程间通信 当后台任务完成后需要及反映至前端页面,可能需要用到 Android 的消息队列机制——Handler。它可以确保即使是在非主线程环境下做出的变化也能安全地反馈回 GUI 线程之上执行相应指令。 #### 示例代码: ```kotlin private val handler = Handler(Looper.getMainLooper()) { msg -> when (msg.what) { REFRESH_LIST -> { adapter.notifyDataSetChanged() true } else -> false } } ``` 每当接收到特定类型的消息后就会触发相应的逻辑分支去调整显示效果[^5]。 --- ### 总结 综上所述,在不同的应用场景下可以选择适合自己的方式来进行 Adapter 列表数据的更新操作。如果是简单的全量替换推荐直接运用 `notifyDataSetChanged();` 如果追求极致效能则建议采纳基于差分算法原理之上的解决方案比如借助于官方库所提供的工具包像上面提到过的那样引入 `DiffUtils`.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值