美文网首页
recyclerview.adapter公共方法、类、接口的作用

recyclerview.adapter公共方法、类、接口的作用

作者: 长点点 | 来源:发表于2023-07-20 10:25 被阅读0次
功能分类 公共内部接口 使用场景
数据绑定 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<Object> 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<Object> 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<Object> 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) {

            }
        }));
    }
}

相关文章

  • 设计模式之抽象工厂模式

    抽象工厂模式 定义鞋类接口,定义公共方法穿鞋子。 定义帽子类接口,定义公共方法戴帽子。 皮鞋实体类 布鞋实体类 皮...

  • @Transactional

    一、作用于接口、接口方法、类以及类方法上 1️⃣当作用于类上时,该类的所有 public 方法将都具有该类型的事务...

  • 接口抽象化设计

    目标:系统设计中存在一些公共接口的设计和接口的一些公共方法的实现以及多种多样的实现类 实现:接口+抽象类+实现类-...

  • 接口和mvp实现流程

    作用:给一部分类做方法级的抽象回调:A类实现接口持有接口对象,传递接口对象给B类,B类调用接口的方法,A类就会执行...

  • 重构之实现统计接口的动机

    何谓统一接口,就是需要一个与子类具有相同接口的超类接口。找到所有子类含有而超类没有的公共方法。把这些方法复制到超类...

  • Spring aop例子

    引入jar包 公共接口 目标类 切面 Spring配置文件 测试方法

  • Spring事务Transactional和动态代理

    相关文章:代理模式引用 虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 S...

  • 接口和抽象类的区别

    接口只能做方法申明,不能包含方法体,抽象类中可以有方法体 接口里定义的变量只能是公共的静态常量,抽象类中的变量可以...

  • 设计模式之工厂模式

    工厂模式 定义鞋类接口,定义公共方法穿鞋子。 皮鞋实体类 布鞋实体类 鞋子工厂接口 布鞋工厂类 皮鞋工厂类 客户端...

  • 接口 interface

    接口定义: 接口就是多个类的公共规范 接口是一种引用数据类型,其最终的内容就是类中定义的抽象方法 格式 注意事项 ...

网友评论

      本文标题:recyclerview.adapter公共方法、类、接口的作用

      本文链接:https://www.haomeiwen.com/subject/itoaudtx.html