Android RecyclerView 上拉加载

01.添加recyclerView的滑动事件

  • 首先给recyclerView添加滑动监听事件。那么我们知道,上拉加载时,需要具备两个条件。第一个是监听滑动到最后一个item,第二个是滑动到最后一个并且是向上滑动。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    // 实现上拉加载重要步骤,设置滑动监听器,RecyclerView自带的ScrollListener
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    //用来标记是否正在向上滑动
    private boolean isSlidingUpward = false;

    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    // 当不滑动的时候
    // 在newState为滑到底部时
    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
    //获取最后一个完全显示的itemPosition
    int lastItemPosition = layoutManager.findLastCompletelyVisibleItemPosition();
    int itemCount = layoutManager.getItemCount();
    //int itemCount1 = adapter.getItemCount();

    // 判断是否滑动到了最后一个item,并且是向上滑动
    if (lastItemPosition == (itemCount - 1) && isSlidingUpward) {
    handler.postDelayed(new Runnable() {
    @Override
    public void run() {
    updateRecyclerView(datas);
    }
    }, 2000);
    }
    }
    }

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

    // 大于0表示正在向上滑动,小于等于0表示停止或向下滑动
    isSlidingUpward = dy > 0;
    }
    });

02.上拉加载分页数据

  • 然后看一下updateRecyclerView的方法。注意这里的刷新数据,可以直接用notifyItemRangeInserted方法,不要用notifyDataSetChanged方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
    * 暴露接口,更新数据源,并修改hasMore的值,如果有增加数据,hasMore为true,否则为false
    */
    public void updateList(List<PersonData> newDatas, boolean hasMore) {
    int size = data.size();
    // 在原有的数据之上增加新数据
    if (newDatas != null) {
    data.addAll(newDatas);
    this.hasMore = hasMore;
    notifyItemRangeInserted(size,newDatas.size());
    }
    }

03.设置上拉加载的底部footer布局

  • 如下所示,核心代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    // 根据返回的ViewType,绑定不同的布局文件,这里只有两种
    if (viewType == normalType) {
    return new MyViewHolder(LayoutInflater.from(mContext)
    .inflate(R.layout.item_news, parent,false));
    } else {
    //这个是上拉加载更多的view
    return new FootHolder(LayoutInflater.from(mContext)
    .inflate(R.layout.view_more, parent,false));
    }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof MyViewHolder){
    PersonData person = data.get(position);
    setBindViewHolder((MyViewHolder)holder,person,position);
    }else {
    setFootBindViewHolder((FootHolder)holder ,position);
    }
    }


    /**
    * 获取条目数量,之所以要加1是因为增加了一条footView
    */
    @Override
    public int getItemCount() {
    return data == null ? 0 : data.size()+1;
    }


    /**
    * 根据条目位置返回ViewType,以供onCreateViewHolder方法内获取不同的Holder
    */
    @Override
    public int getItemViewType(int position) {
    if (position == getItemCount() - 1) {
    return footType;
    } else {
    return normalType;
    }
    }

04.显示和隐藏footer布局

  • 一般情况下,滑动底部最后一个item,然后显示footer上拉加载布局,然后让其加载500毫秒,最后加载出下一页数据后再隐藏起来。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    private void setFootBindViewHolder(final FootHolder holder, int position) {
    // 之所以要设置可见,是因为我在没有更多数据时会隐藏了这个footView
    holder.tv_more.setVisibility(View.VISIBLE);
    // 只有获取数据为空时,hasMore为false,所以当我们拉到底部时基本都会首先显示“正在加载更多...”
    if (hasMore) {
    // 不隐藏footView提示
    fadeTips = false;
    if (data.size() > 0) {
    // 如果查询数据发现增加之后,就显示正在加载更多
    holder.tv_more.setText("逗比,正在加载更多...");
    }
    } else {
    if (data.size() > 0) {
    // 如果查询数据发现并没有增加时,就显示没有更多数据了
    holder.tv_more.setText("逗比,没有更多数据了");

    // 然后通过延时加载模拟网络请求的时间,在500ms后执行
    mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
    // 隐藏提示条
    holder.tv_more.setVisibility(View.GONE);
    // 将fadeTips设置true
    fadeTips = true;
    // hasMore设为true是为了让再次拉到底时,会先显示正在加载更多
    hasMore = true;
    }
    }, 500);
    }
    }
    }