首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

notifyDatasetChanged()之后RecyclerView闪烁

notifyDatasetChanged() 是 Android 开发中用于通知 RecyclerView 数据集发生变化的方法。当调用此方法时,RecyclerView 会重新绑定数据并刷新界面。然而,有时会出现闪烁现象,这通常是由于以下原因造成的:

原因分析

  1. 视图重绘:当数据集发生变化时,RecyclerView 需要重新绘制视图。如果重绘过程中布局计算不准确或者数据更新频繁,可能会导致视图闪烁。
  2. 动画效果RecyclerView 默认启用了动画效果,当数据集发生变化时,动画可能会导致视图闪烁。
  3. 布局问题:如果 RecyclerView 的布局管理器或布局文件设置不当,也可能导致视图闪烁。

解决方案

  1. 减少数据更新频率:避免频繁调用 notifyDatasetChanged(),可以考虑使用 DiffUtil 来计算数据集的变化,并只更新变化的部分。
代码语言:txt
复制
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffCallback(oldData, newData));
diffResult.dispatchUpdatesTo(adapter);
  1. 关闭动画效果:可以通过设置 RecyclerView 的动画效果为 null 来关闭动画。
代码语言:txt
复制
recyclerView.setItemAnimator(null);
  1. 优化布局:确保 RecyclerView 的布局管理器和布局文件设置合理,避免不必要的视图嵌套和复杂的布局计算。
  2. 使用 notifyItemRangeChanged():如果只有部分数据发生变化,可以使用 notifyItemRangeChanged() 来通知 RecyclerView 只更新变化的部分。
代码语言:txt
复制
adapter.notifyItemRangeChanged(startPosition, itemCount);

示例代码

以下是一个简单的示例,展示了如何使用 DiffUtil 来优化数据更新:

代码语言:txt
复制
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private List<MyData> dataList;

    public MyAdapter(List<MyData> dataList) {
        this.dataList = dataList;
    }

    public void updateData(List<MyData> newData) {
        DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffCallback(dataList, newData));
        dataList.clear();
        dataList.addAll(newData);
        diffResult.dispatchUpdatesTo(this);
    }

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

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        MyData data = dataList.get(position);
        holder.textView.setText(data.getText());
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

        ViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.textView);
        }
    }

    static class MyDiffCallback extends DiffUtil.Callback {
        private List<MyData> oldData;
        private List<MyData> newData;

        MyDiffCallback(List<MyData> oldData, List<MyData> newData) {
            this.oldData = oldData;
            this.newData = newData;
        }

        @Override
        public int getOldListSize() {
            return oldData.size();
        }

        @Override
        public int getNewListSize() {
            return newData.size();
        }

        @Override
        public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
            return oldData.get(oldItemPosition).getId() == newData.get(newItemPosition).getId();
        }

        @Override
        public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
            return oldData.get(oldItemPosition).equals(newData.get(newItemPosition));
        }
    }
}

参考链接

通过以上方法,可以有效减少 notifyDatasetChanged() 调用后 RecyclerView 的闪烁现象。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券