RecyclerView.Adapter → ListAdapter

RecyclerView.Adapter → ListAdapter

老写法(Java)

java 复制代码
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private List<Item> items = new ArrayList<>();

    public void setData(List<Item> newItems) {
        items.clear();
        items.addAll(newItems);
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_row, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Item item = items.get(position);
        holder.tvName.setText(item.getName());
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvName;
        ViewHolder(View itemView) {
            super(itemView);
            tvName = itemView.findViewById(R.id.tv_name);
        }
    }
}

问题在哪里

notifyDataSetChanged() 会刷新整个列表,没有动画,滚动位置也可能跳动。数据量一大明显卡顿,用户体验差。

新写法(Kotlin + ListAdapter)

kotlin 复制代码
class MyAdapter : ListAdapter<Item, MyAdapter.ViewHolder>(DiffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_row, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.tvName.text = getItem(position).name
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvName: TextView = itemView.findViewById(R.id.tv_name)
    }

    companion object {
        private val DiffCallback = object : DiffUtil.ItemCallback<Item>() {
            override fun areItemsTheSame(oldItem: Item, newItem: Item) =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Item, newItem: Item) =
                oldItem == newItem
        }
    }
}

data class Item(val id: Long, val name: String)

数据更新时只需:

kotlin 复制代码
adapter.submitList(newList)

一句话注意

submitList() 内部在后台线程做 diff 计算,不会卡主线程。但注意不要在高频更新的场景(比如每秒数十次)下反复 new 一个新 list 往里传,容易造成资源浪费。

如果只是列表里某一项的某个字段变了,需要重写 areContentsTheSame,否则 notifyDataSetChanged() 依然需要手动调用。areItemsTheSame 是判断"是不是同一条",通常比 ID;areContentsTheSame 是判断"内容是否变了",通常 equals()


Java Android 老项目迁移系列,持续更新中。

相关推荐
库克克8 分钟前
【C++ 】内联函数
java·开发语言·c++
zh_xuan14 分钟前
java 虚拟线程
java·开发语言·虚拟线程
jason成都34 分钟前
RTKLIB Java 移植踩坑复盘:卡尔曼滤波核心逻辑修复与滑坡场景实测验证
java·开发语言
老毛肚1 小时前
juc线程通信
java·开发语言·jvm
花颜yyds2 小时前
Java 开发基础速查手册
java
没钥匙的锁12 小时前
05-Java面向对象构造器与封装
java·开发语言
aaPIXa6223 小时前
C++采样引导优化SPGO——比PGO更智能的编译器决策新方案
java·c++·人工智能
蓝银草同学3 小时前
Stream 实战:博客列表排序、过滤与分页(AI 辅助学习 Java 8)
java·前端·后端
某不知名網友3 小时前
C/C++动态内存管理,智能指针及RAlI思想。
java·c语言·c++
沫离痕5 小时前
Cassandra 4.0.11 Docker 安装与配置手册
java·spring boot