Android——recyclerview.adapter公共方法、类、接口的作用简述

功能分类公共内部接口使用场景
数据绑定onCreateViewHolder(ViewGroup parent, int viewType)
onBindViewHolder(VH holder, int position)
getItemCount()创建和更新 ViewHolder 及其关联的视图
数据变化notifyDataSetChanged()
notifyItemChanged(int position)
notifyItemInserted(int position)
notifyItemRemoved(int position)
notifyItemMoved(int fromPosition, int toPosition)
notifyItemRangeChanged(int positionStart, int itemCount)
notifyItemRangeInserted(int positionStart, int itemCount)
notifyItemRangeRemoved(int positionStart, int itemCount)通知 RecyclerView 数据集的变化,触发视图的重新绘制或布局
数据观察registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer)
unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer)注册或取消注册观察者对象,监听数据集的变化
数据标识setHasStableIds(boolean hasStableIds)
getItemId(int position)设置是否为每个列表项分配一个稳定的 ID,用于优化性能或实现动画效果
视图类型getItemViewType(int position)返回给定位置的列表项的视图类型,用于支持不同的布局

RecyclerView.Adapter 是一个抽象类,它定义了 RecyclerView 的数据和视图的绑定器。它有三个抽象方法需要重写:

  • onCreateViewHolder(ViewGroup parent, int viewType) :每当 RecyclerView 需要创建新的 ViewHolder 时,它都会调用此方法。此方法会创建并初始化 ViewHolder 及其关联的 View ,但不会填充视图的内容,因为 ViewHolder 此时尚未绑定到具体数据。
  • onBindViewHolder(VH holder, int position) : RecyclerView 调用此方法将 ViewHolder 与数据相关联。此方法会提取适当的数据,并使用该数据填充 ViewHolder 的布局。
  • getItemCount() : RecyclerView 调用此方法来获取数据集的大小。 RecyclerView 使用此方法来确定什么时候没有更多的列表项可以显示。

除了这三个抽象方法,RecyclerView.Adapter 还有一些公共方法、类、接口,它们的作用如下:

  • setHasStableIds(boolean hasStableIds) :设置是否为每个列表项分配一个稳定的 ID。如果为 true ,则必须重写 getItemId(int position) 方法,以便为每个列表项返回一个唯一的 ID。
  • getItemId(int position) :返回给定位置的列表项的 ID。如果 setHasStableIds(boolean hasStableIds) 设置为 false ,则默认返回 NO_ID 。如果设置为 true ,则必须重写此方法,以便为每个列表项返回一个唯一的 ID。
  • getItemViewType(int position) :返回给定位置的列表项的视图类型。默认情况下,所有列表项都使用同一种视图类型。如果您想使用不同的视图类型,您可以重写此方法,并根据位置返回不同的整数值。
  • notifyDataSetChanged() :通知 RecyclerView 数据集已经发生了变化,需要重新绘制所有列表项。
  • notifyItemChanged(int position) :通知 RecyclerView 指定位置的列表项已经发生了变化,需要重新绘制该列表项。
  • notifyItemInserted(int position) :通知 RecyclerView 在指定位置插入了一个新的列表项,需要重新计算布局。
  • notifyItemRemoved(int position) :通知 RecyclerView 在指定位置删除了一个列表项,需要重新计算布局。
  • notifyItemMoved(int fromPosition, int toPosition) :通知 RecyclerView 在指定位置之间移动了一个列表项,需要重新计算布局。
  • notifyItemRangeChanged(int positionStart, int itemCount) :通知 RecyclerView 在指定范围内的列表项已经发生了变化,需要重新绘制这些列表项。
  • notifyItemRangeInserted(int positionStart, int itemCount) :通知 RecyclerView 在指定范围内插入了一些新的列表项,需要重新计算布局。
  • notifyItemRangeRemoved(int positionStart, int itemCount) :通知 RecyclerView 在指定范围内删除了一些列表项,需要重新计算布局。
  • registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) :注册一个观察者对象,用于监听数据集的变化。
  • unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) :取消注册一个观察者对象,不再监听数据集的变化。

RecyclerView.AdapterDataObserver 是一个抽象类,它定义了监听数据集变化的观察者。它有以下几个回调方法:

  • onChanged() :当数据集发生任何变化时调用。
  • onItemRangeChanged(int positionStart, int itemCount) :当指定范围内的列表项发生变化时调用。
  • onItemRangeChanged(int positionStart, int itemCount, Object payload) :当指定范围内的列表项发生变化时调用。 payload 参数是一个可选的对象,用于传递部分更新的信息。
  • onItemRangeInserted(int positionStart, int itemCount) :当指定范围内插入新的列表项时调用。
  • onItemRangeRemoved(int positionStart, int itemCount) :当指定范围内删除列表项时调用。
  • onItemRangeMoved(int fromPosition, int toPosition, int itemCount) :当指定范围内的列表项移动时调用。

局部刷新相关

notify 系列方法功能使用场景搭配方法
notifyDataSetChanged()通知 RecyclerView 数据集发生了任何变化,需要重新绘制所有列表项当数据集发生了大量或不确定的变化时,或者不需要动画效果时
notifyItemChanged(int position)通知 RecyclerView 指定位置的列表项发生了变化,需要重新绘制该列表项当数据集中某个元素的内容发生了变化时,或者需要显示某个元素的选中状态时onBindViewHolder(VH holder, int position)
notifyItemChanged(int position, Object payload)通知 RecyclerView 指定位置的列表项发生了变化,需要重新绘制该列表项,并传递部分更新的信息当数据集中某个元素只有部分内容发生了变化时,或者需要优化性能时onBindViewHolder(VH holder, int position, List payloads)
notifyItemInserted(int position)通知 RecyclerView 在指定位置插入了一个新的列表项,需要重新计算布局,并显示插入动画效果当数据集中增加了一个新元素时,或者需要显示插入动画效果时onCreateViewHolder(ViewGroup parent, int viewType)
notifyItemRemoved(int position)通知 RecyclerView 在指定位置删除了一个列表项,需要重新计算布局,并显示删除动画效果当数据集中删除了一个元素时,或者需要显示删除动画效果时
notifyItemMoved(int fromPosition, int toPosition)通知 RecyclerView 在指定位置之间移动了一个列表项,需要重新计算布局,并显示移动动画效果当数据集中某个元素的位置发生了变化时,或者需要显示移动动画效果时
notifyItemRangeChanged(int positionStart, int itemCount)通知 RecyclerView 在指定范围内的列表项发生了变化,需要重新绘制这些列表项,并批量刷新多个列表项当数据集中一段连续的元素内容发生了变化时,或者需要批量刷新时onBindViewHolder(VH holder, int position)
notifyItemRangeChanged(int positionStart, int itemCount, Object payload)通知 RecyclerView 在指定范围内的列表项发生了变化,需要重新绘制这些列表项,并传递部分更新的信息,并批量刷新多个列表项当数据集中一段连续的元素只有部分内容发生了变化时,或者需要优化性能时onBindViewHolder(VH holder, int position, List payloads)
notifyItemRangeInserted(int positionStart, int itemCount)通知 RecyclerView 在指定范围内插入了一些新的列表项,需要重新计算布局,并批量插入多个列表项当数据集中增加了一段连续的新元素时,或者需要批量插入时onCreateViewHolder(ViewGroup parent, int viewType)
notifyItemRangeRemoved(int positionStart, int itemCount)通知 RecyclerView 在指定范围内删除了一些列表项,需要重新计算布局,并批量删除多个列表项当数据集中删除了一段连续的元素时,或者需要批量删除时

notifyItemChanged(int position, Object payload) 局部刷新 UI 的例子。

这个方法的作用是通知 RecyclerView 指定位置的列表项发生了变化,需要重新绘制该列表项,并传递部分更新的信息。使用场景是当数据集中某个元素只有部分内容发生了变化时,或者需要优化性能时。

例如,假设您有一个 RecyclerView 显示了一些音乐播放列表,每个列表项包含了歌曲的标题、作者、时长和播放状态。当您点击某个列表项时,您想要改变它的播放状态,并显示一个播放图标。但是您不想要重新绘制整个列表项,因为其他信息没有变化。这时,您可以使用 notifyItemChanged(int position, Object payload) 方法来实现局部刷新。

具体的步骤如下:

  • 在 Adapter 中定义一个 ViewHolder 类,它是一个封装了列表项布局的 View 的容器。您可以在 ViewHolder 的构造方法中初始化列表项的视图组件,并在 onBindViewHolder(VH holder, int position) 方法中为它们设置数据。
  • 在 Adapter 中重写 onBindViewHolder(VH holder, int position, List payloads) 方法,它会在 notifyItemChanged(int position, Object payload) 方法被调用时触发。在这个方法中,您可以根据 payload 参数来判断是否需要局部刷新,以及如何刷新。如果 payload 参数为空或不符合您的要求,您需要调用 super.onBindViewHolder(holder,position, payloads) 方法来触发全局刷新。
  • 在 Activity 或 Fragment 中为 RecyclerView 设置点击事件监听器,当某个列表项被点击时,获取它的位置和数据,并调用 notifyItemChanged(int position, Object payload) 方法来通知 Adapter 局部刷新。payload 参数可以是任何对象,您可以根据自己的需求来定义它。

以下是一个简单的示例代码

// 定义一个数据类
public class Song {
    private String title; // 歌曲标题
    private String artist; // 歌曲作者
    private String duration; // 歌曲时长
    private boolean playing; // 歌曲播放状态

    public Song(String title, String artist, String duration, boolean playing) {
        this.title = title;
        this.artist = artist;
        this.duration = duration;
        this.playing = playing;
    }

    // 省略 getter 和 setter 方法
}

// 定义一个 Adapter 类
public class SongAdapter extends RecyclerView.Adapter<SongAdapter.SongViewHolder> {
    private List<Song> songList; // 数据集

    public SongAdapter(List<Song> songList) {
        this.songList = songList;
    }

    // 定义一个 ViewHolder 类
    public static class SongViewHolder extends RecyclerView.ViewHolder {
        public TextView tvTitle; // 歌曲标题视图
        public TextView tvArtist; // 歌曲作者视图
        public TextView tvDuration; // 歌曲时长视图
        public ImageView ivPlay; // 歌曲播放图标视图

        public SongViewHolder(View view) {
            super(view);
            tvTitle = (TextView) view.findViewById(R.id.tv_title);
            tvArtist = (TextView) view.findViewById(R.id.tv_artist);
            tvDuration = (TextView) view.findViewById(R.id.tv_duration);
            ivPlay = (ImageView) view.findViewById(R.id.iv_play);
        }
    }

    @Override
    public SongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 创建并返回 ViewHolder 对象
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.song_list_item, parent, false);
        return new SongViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(SongViewHolder holder, int position) {
        // 为 ViewHolder 的视图组件设置数据
        Song song = songList.get(position);
        holder.tvTitle.setText(song.getTitle());
        holder.tvArtist.setText(song.getArtist());
        holder.tvDuration.setText(song.getDuration());
        holder.ivPlay.setVisibility(song.isPlaying() ? View.VISIBLE : View.INVISIBLE);
    }

    @Override
    public void onBindViewHolder(SongViewHolder holder, int position, List<Object> payloads) {
        // 判断是否需要局部刷新
        if (!payloads.isEmpty()) {
            // 如果 payload 参数是一个布尔值,表示播放状态发生了变化
            if (payloads.get(0) instanceof Boolean) {
                boolean playing = (Boolean) payloads.get(0);
                // 只刷新播放图标的可见性
                holder.ivPlay.setVisibility(playing ? View.VISIBLE : View.INVISIBLE);
            }
        } else {
            // 如果 payload 参数为空或不符合要求,调用全局刷新
            super.onBindViewHolder(holder, position, payloads);
        }
    }

    @Override
    public int getItemCount() {
        // 返回数据集的大小
        return songList.size();
    }
}

// 定义一个 Activity 或 Fragment 类
public class SongActivity extends AppCompatActivity {
    private RecyclerView recyclerView; // RecyclerView 控件
    private SongAdapter adapter; // Adapter 对象
    private List<Song> songList; // 数据集

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_song);

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

        // 初始化数据集
        songList = new ArrayList<>();
        songList.add(new Song("Hello", "Adele", "4:55", false));
        songList.add(new Song("Shape of You", "Ed Sheeran", "3:53", false));
        songList.add(new Song("Despacito", "Luis Fonsi", "4:42", false));
        songList.add(new Song("Bad Guy", "Billie Eilish", "3:14", false));
        songList.add(new Song("Blinding Lights", "The Weeknd", "3:20", false));

        // 创建并设置 Adapter 对象
        adapter = new SongAdapter(songList);
        recyclerView.setAdapter(adapter);

        // 设置布局管理器和分割线
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

        // 设置点击事件监听器
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new RecyclerTouchListener.ClickListener() {
            @Override
            public void onClick(View view, int position) {
                // 获取点击位置的数据对象
                Song song = songList.get(position);
                // 改变播放状态
                song.setPlaying(!song.isPlaying());
                // 通知 Adapter 局部刷新,并传递播放状态作为 payload 参数
                adapter.notifyItemChanged(position, song.isPlaying());
            }

            @Override
            public void onLongClick(View view, int position) {

            }
        }));
    }
}

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值