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 老项目迁移系列,持续更新中。

相关推荐
J2虾虾1 小时前
Spring AI Alibaba - 人工介入(Human-in-the-Loop)
java·人工智能·spring
Old Uncle Tom1 小时前
Harness Engineering 综述
java·开发语言·数据库
星原望野2 小时前
JAVA:策略模式的实战使用
java·开发语言·策略模式
LJianK12 小时前
java多态
java·开发语言·python
z落落2 小时前
C# 构造函数(无参/有参/重载/this)+析构函数(终结器)|GC 垃圾回收
java·开发语言·c#
武子康2 小时前
Java-12 深入浅出 MyBatis 二级缓存详解:跨 SqlSession 共享与失效机制
java·后端
考虑考虑2 小时前
JDK9中的Set.of()使用注意
java·后端·java ee
plainGeekDev2 小时前
findViewById → ViewBinding
java·kotlin·gradle
yz_aiks2 小时前
IDEA终端配置oh-my-zsh实战:安装、插件与日常使用技巧
java·ide·intellij-idea