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

2023-07-20  本文已影响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 的数据和视图的绑定器。它有三个抽象方法需要重写:

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

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

局部刷新相关

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) 方法来实现局部刷新。

具体的步骤如下:

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

// 定义一个数据类
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) {

            }
        }));
    }
}
上一篇 下一篇

猜你喜欢

热点阅读