Android开发笔记:RecyclerView(二)刷新与点击事件

本文探讨了在Android开发中,如何在RecyclerView中处理刷新和点击事件。在RecyclerView的刷新部分,介绍了全量刷新(notifyDataSetChanged)、局部刷新(notifyItemInserted, notifyItemRangeChanged等)和控件刷新的概念。接着,文章讨论了两种实现RecyclerView点击事件的方法:1. 直接在Item的View上添加点击事件,利用onBindViewHolder设置监听;2. 使用RecyclerView的addOnItemTouchListener,通过监听触摸事件来处理点击。" 1589888,43211,SAP中自定义打印纸张设置教程,"['SAP应用', '服务器配置', 'Windows应用']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RecyclerView(一)主要介绍了RecyclerView基础的使用方式,用于列表展示大量数据,介绍了一些方法和类的关系。列表中的数据通过一个LIst数据结构保存,通过adapter进行绑定和渲染,在使用RecyclerView时,不可避免的会遇到展示列表信息的变更,即List内容的更改,RecyclerView不会自动的展示更改,需要进行刷新操作。

RecyclerView的刷新

每个列表都对应了一个List的数据结构,对于类表的增删改都是通过对List进行的,本文在上一篇文章的基础上增加一个按钮,点击按钮后,增加adapter中list的数据:

btn = (Button)findViewById(R.id.mbtn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayList<Integer> data = new ArrayList<>();
                for(int i=10;i<20;i++){
                    data.add(i);
                }
                adapter.addData(data);
            }
        });

adapter中addData方法,直接在原来的List后添加新的数据,如下:

public void addData(ArrayList<Integer> data){
        this.data.addAll(data);
    }

运行的效果为:

可以发现按钮点击后,只改变list数据,列表并没有自动更新。上篇文章中设置了自定义间隔,点击按钮前,5号item是最后一个,所以右边的间隔设置为50,点击按钮后,由于item5不是list数据中的最后一位,渲染时间隔就变为了12.

要使列表随着list的更新变化,就要进行刷新操作,说白了就是要告诉RecyclerView,数据发生了变化。RecyclerVIew的刷新我把他分为三个等级:全部刷新、局部刷新、控件刷新。

  • 全部刷新顾名思义,对于列表中的所有items都进行刷新,重新绘制,对应的方法是:notifyDataSetChanged,这样可以把新的数据也刷新出来。ListView的刷新方式就是全部刷新,缺点就是对于没有变化的item数据,也要强制刷新,效率不高。
  • 局部刷新是指只刷新部分items,有两个对应的方法:
    //更新指定位置
    public final void notifyItemChanged(int position) {
                mObservable.notifyItemRangeChanged(position, 1);
            }
    
    /**
     * 更新一部分位置
     * 从positionStart开始itemCount个数据
     */
    public void notifyItemRangeChanged(int positionStart, int itemCount) {
                notifyItemRangeChanged(positionStart, itemCount, null);
            }

     

  • 控件刷新是更小一层的刷新,只刷新item中的一个控件,比如很多人刷新时遇到的图片闪动问题,就是在刷新时,虽然Item中图片没有发生变化,但是由于整个item都重新绘制,所以图片出现了闪动,这个时候就需要用到控件刷新,只刷新部分控件。可以使用使用:
    public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
                mObservable.notifyItemRangeChanged(positionStart, itemCount, payload);
            }

    当payload为NULL时,即是局部刷新,需要重写onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) 方法来实现具体控件的更新逻辑

    @Override
        public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
            //为空时刷新整个item
            if (payloads.isEmpty()) {
                super.onBindViewHolder(holder, position, payloads);
            } else {
            //实现ViewHolder中控件的更新逻辑
                ...
            }
        }

    RecyclerView列表的点击事件

列表除了展示数据之外,还需要对点击事件进行响应,ListView中可以直接通过setItemClickListener来设置列表点击的监听,而RecyclerView没有给我们提供这样的接口,所以对于RecyclerView列表的点击需要我们自己创建,目前主流的方法有两种种

  • 对Item的View添加点击事件
  • 通过RecyclerView的addOnItemTouchListener()来实现

1.Item的View添加点击事件

虽然RecyclerView没有提供item的点击事件接口,但是由于每个item的视图是由我们自己定义的,可以通过对视图控件的点击事件进行监听,从而实现item的点击监听。

列表再滚动的时候,会通过onbind()方法得到要显示的视图,可以再此方法中对View进行点击监听。这里最好建一个全局的listener,通过view.getID或getTag等方式判断点击的是哪个item,而不是给每个view 都创建一个监听器,这样在列表滑动时可以避免大量的对象创建和销毁。保证滑动的性能。

@NonNull
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        context = parent.getContext();
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item_view,parent,false);
        MyAdapter.ViewHolder viewHolder = new MyAdapter.ViewHolder(view);
        view.setOnClickListener(this);
        view.setOnLongClickListener(this);
        return viewHolder;
    }

在adapter中实现View点击后的具体逻辑即可,

@Override
    public void onClick(View v) {
        int position = mRecyclerView.getChildAdapterPosition(v);
        Toast.makeText(context,"第"+position+"个被点击",Toast.LENGTH_SHORT).show();
    }
@Override
    public boolean onLongClick(View v) {
        int position = mRecyclerView.getChildAdapterPosition(v);
        ...//添加长按处理的逻辑
        return true;
    }

但是使用ListView的时候,我们的点击事件是通过adapter.setOnItemClickListener设置的,直接在Activity中就可以设置,比较方便,封装更好,所以我们也要想办法将接口暴露出来,方便调用。

首先创建一个接口

interface ItemClickListener{
        void onclick(int position);
        void onLongClick(int position);
    }

在adapter中View的点击事件处理中,不写具体处理逻辑,只执行接口的方法,具体逻辑由实现了接口方法的类去实现

private ItemClickListener itemClickListener;

@Override
    public boolean onLongClick(View v) {
        int position = mRecyclerView.getChildAdapterPosition(v);
        itemClickListener.onLongClick(position);
    }

public void onClick(View v) {
        int position = mRecyclerView.getChildAdapterPosition(v);
        itemClickListener.onclick(position);
    }

然后将实现了接口的类传进来,就可以实现调用。例如我们在Activity中实现接口:

mAdapter.setItemClickListener(new MyAdapter.ItemClickListener() {
            @Override
            public void onclick(int position) {
                Toast.makeText(MainActivity.this,"第"+position+"位置点击",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onLongClick(int position) {
                //长按事件
            }
        });

2.addOnItemTouchListener()实现监听

addOnItemTouchListener是RecyclerVIew中的一个内部接口,可以对RecyclView中的触摸事件进行拦截,接口方法如下:

@Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return false;
    }
    
    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }
    
    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }

在onInterceptTouchEvent中可以获取当前触摸位置对应的子item view,使用GestureDetector判断点击状态,决定是否要把事件拦截,在拦截的时候同时添加一个回调方法处理。实现起来比较麻烦,后续再写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值