android开发-RecyclerView上拉加载

需求

  • 实现功能——分批上拉加载。如分批加载每次30个,第一次显示30个item,上拉到底后,数据再添入30个,一共可显示60个item。
  • 上拉加载的控件——RecyclerView。
  • 上拉加载的时机——此次最后一个item在屏幕完全可见时(也可以是部分可见)。

实现(滑动刷新数据部分)

  • 准备添加下一批数据的方法

 /**
     * 分批加载 增加此批数据
     */
    private void addNextDatas() {
//mPickRecipesList是可显示的所有item列表,有点冗余,但我复用了mTempList,这样是以免我这里数据出错
//mTempList是交给RecyclerView适配器的列表,通过改变这个列表数据,然后局部刷新

        if (mPickRecipesList != null) {
            int i = 0;

            //目前已经注入adapter的个数
            int position = mCurrentCount;

            //添加下一批数据
            while (position < mRecipes.size() && i < mAddCount) {
                mPickRecipesList.add(mRecipes.get(position));
                position++;
                i++;
            }
            mTempList = mPickRecipesList;
            mCurrentCount = mCurrentCount + mAddCount;
        }
    }
  • 准备判断RecyclerView滑到底部的方法(根据最后一个item是否完全可见)

View对象的getLocalVisibleRect(Rect rect)方法

首先Rect对象,是一个记录坐标的对象。有left、right、top、botton四个参数。分别代表

left:View的 左边 离屏幕 左边 的距离;

right:View的 右边 离屏幕 左边 的距离;

top:View的 顶部 离屏幕 顶部 的距离;

bottom:View的 底部 离屏幕 顶部 的距离;

是滴,我没有写错,就是这样的。

而确认RecyclerView中的item是否可见时,它的坐标是以自己为起点。

当使用recyclerView.getChildAt(最后一个item下标),获得最后一个item的View,当它的left=top=0,right=宽,bottom=高时,这个View在屏幕完全可见;当它的left=0,top!=0,right<宽,bottom<高,这个View在屏幕部分可见;

给getLocalVisibleRect(Rect rect)传入new Rect(0, 0, view.getWidth(), view.getHeight()),返回true可见,否则不可见。

 /**
     * 确定列表目前最后一个完全可见
     *
     * @param view
     * @return
     */
    private boolean isOnScreen(View view) {
        if (view != null) {
            int width = view.getWidth();
            int height = view.getHeight();
            Rect rect = new Rect(0, 0, width, height);
            return view.getLocalVisibleRect(rect);
        } else {
            MyLog.d(TAG, "isOnScreen view is null");
        }
        return false;
    }
  • 使用Handler处理界面刷新

 private final Handler mHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            MyLog.d(TAG, "message is" + msg.what);
            switch (msg.what) {
//mRecipes是我所有要加载的总item列表
//mCurrentCount记录当前所有可显示的item数,也是下一批要放入的数据的开始下标
               
                case SCROLL_IDLE:
                    //到达当前底部 但数据还没加载完
                    if (mRecipes != null && mCurrentCount < mRecipes.size()) {

                        //记录下一批要放入的数据的开始下标,方便局部刷新
                        int before = mRecipeGirdAdapter.getItemCount();

                        //增加下一批数据
                        addNextDatas();

                        //局部刷新
                        mRecipeGirdAdapter.notifyItemRangeChanged(before, mRecipeGirdAdapter.getItemCount() - before);
                    }

                    break;
            }
        }
    };
  • 给对应RecyclerView设置滑动监听事件

滑动时,根据判断最后一个item是否可见,结合滑动状态,判断是否滑到底部。

当非静止状态时候,不进行数据更新,防止边滑动边刷新会卡顿。

 /**
     * 监听滚动事件
     */
    private void initRecyclerView() {
        if (mGridView != null) {
            mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    //获取目前展示的列表最后一个item的view
                    boolean visible = isOnScreen(recyclerView.getChildAt(mCurrentCount - 1));
                    //最后一个item可见
                    if (visible) {
                        switch (newState) {
                            case RecyclerView.SCROLL_STATE_IDLE:
                                //静止状态 &&  加载
                                if (!mHandler.hasMessages(SCROLL_IDLE)) {
                                    mHandler.sendEmptyMessage(SCROLL_IDLE);
                                }
                                break;

                            case RecyclerView.SCROLL_STATE_DRAGGING:
                            case RecyclerView.SCROLL_STATE_SETTLING:
                                //滑动时候到达最底部 不加载
                                if (mHandler.hasMessages(SCROLL_IDLE)) {
                                    mHandler.removeMessages(SCROLL_IDLE);
                                }
                                break;
                        }
                    }
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                }
            });
        }
    }

希望你我日益成长。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值