RecyclerView加载更多数据的三种不同的实现方式

  • Post author:
  • Post category:其他


上拉加载更多数据通过监听RecyclerView的滚动事件RecyclerView.OnScrollListener()实现的,它提供了两个方法:

        /**
         * 当RecyclerView的滑动状态改变时触发
         */
        public void onScrollStateChanged(RecyclerView recyclerView, int newState){}

        /**
         * 当RecyclerView滑动时触发
         * 类似点击事件的MotionEvent.ACTION_MOVE
         */
        public void onScrolled(RecyclerView recyclerView, int dx, int dy){}

RecyclerView的滑动状态有如下三种:

    /**
     * The RecyclerView is not currently scrolling.
     * 手指离开屏幕
     */
    public static final int SCROLL_STATE_IDLE = 0;

    /**
     * The RecyclerView is currently being dragged by outside input such as user touch input.
     * 手指触摸屏幕
     */
    public static final int SCROLL_STATE_DRAGGING = 1;

    /**
     * The RecyclerView is currently animating to a final position while not under
     * outside control.
     * 手指加速滑动并放开,此时滑动状态伴随SCROLL_STATE_IDLE
     */
    public static final int SCROLL_STATE_SETTLING = 2;


第一种实现:滑动到最后一个item时自动触发的


与手指是否在屏幕上无关,即与滑动状态无关。因此,实现这种效果只需要在public void onScrolled(RecyclerView recyclerView, int dx, int dy) 方法中操作,无需关注当时的滑动状态:

  @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                Log.d("test", "onScrolled");

                int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
                if (lastVisibleItemPosition + 1 == adapter.getItemCount()) {
                    Log.d("test", "loading executed");

                    boolean isRefreshing = swipeRefreshLayout.isRefreshing();
                    if (isRefreshing) {
                        adapter.notifyItemRemoved(adapter.getItemCount());
                        return;
                    }
                    if (!isLoading) {
                        isLoading = true;
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                getData();
                                Log.d("test", "load more completed");
                                isLoading = false;
                            }
                        }, 1000);
                    }
                }
            }


第二种实现:当且仅当滑动到最后一项并且手指上拉时才执行上拉加载更多


需要配合onScrollStateChanged(RecyclerView recyclerView, int newState的使用,可以将代码改为:

 @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                Log.d("test", "StateChanged = " + newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItemPosition + 1 == adapter.getItemCount()) {
                    Log.d("test", "loading executed");

                    boolean isRefreshing = swipeRefreshLayout.isRefreshing();
                    if (isRefreshing) {
                        adapter.notifyItemRemoved(adapter.getItemCount());
                        return;
                    }
                    if (!isLoading) {
                        isLoading = true;
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                getData();
                                Log.d("test", "load more completed");
                                isLoading = false;
                            }
                        }, 1000);
                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                Log.d("test", "onScrolled");

                lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();

            }


第三种是:每次滚动到最后一项都触发的加载更多:

  @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
                if (lastVisibleItemPosition + 1 == adapter.getItemCount()) {
                    Log.d("test", "loading executed");

                    boolean isRefreshing = swipeRefreshLayout.isRefreshing();
                    if (isRefreshing) {
                        adapter.notifyItemRemoved(adapter.getItemCount());
                        return;
                    }
                    if (!isLoading) {
                        isLoading = true;
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                getData();
                                Log.d("test", "load more completed");
                                isLoading = false;
                            }
                        }, 1000);
                    }
                }
            }

参考:

使用SwipeRefreshLayout和RecyclerView实现仿“简书”下拉刷新和上拉加载更多