美文网首页week.io
RecyclerView,你为什么不回调 onScrolled

RecyclerView,你为什么不回调 onScrolled

作者: HelloVass | 来源:发表于2015-11-20 16:56 被阅读3623次

    RecyclerView

    这个控件带来的插件化编程体验良好的性能都在不断吸引大家使用 ta,github 上已经有很多基于 RecyclerView 的开源项目,并且为 RecyclerView 增加了很多牛逼的 feature。这次,我也实现了一个自己的 RecyclerView。

    feature-1 滑动到底部加载更多

    其实,实现 LoadMore 功能并不难,网上也一堆分享,这里我主要参考了秋百万的 cube-sdk 中的 recycler-load-more 分支

    我的疑惑

    实现后的效果.gif
    当 RecyclerView 中只有一条数据时,无论我怎么 scroll(滚动),OnScrollListener 里 onScrolled(RecyclerView recyclerView, int dx, int dy) 这个重要的回调方法 似乎是被谁吃掉了一样,再也没有被触发了,这是为什么?

    不科学,断点调试大法启动

    同事带我深入了 RecyclerView 源码寻找这个方法被吃掉的原因。

    // 省略在源码中的艰辛寻找过程...

    最后,定位到了 LinearLayoutManager 里的这个方法

    int scrollBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
            if (getChildCount() == 0 || dy == 0) {
                return 0;
            }
            mLayoutState.mRecycle = true;
            ensureLayoutState();
            final int layoutDirection = dy > 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START;
            final int absDy = Math.abs(dy);
            updateLayoutState(layoutDirection, absDy, true, state);
            final int freeScroll = mLayoutState.mScrollingOffset;
            final int consumed = freeScroll + fill(recycler, mLayoutState, state, false);
            if (consumed < 0) {
                if (DEBUG) {
                    // 没有更多元素可以 scroll !!!
                    Log.d(TAG, "Don't have any more elements to scroll");
                }
                return 0;
            }
            final int scrolled = absDy > consumed ? layoutDirection * consumed : dy;
            mOrientationHelper.offsetChildren(-scrolled);
            if (DEBUG) {
                Log.d(TAG, "scroll req: " + dy + " scrolled: " + scrolled);
            }
            mLayoutState.mLastScrollDelta = scrolled;
            return scrolled;
        }
    

    分析

    看到这里,已经清楚很多了,注释里已经说明,consumed < 0 表明没有更多元素可以滚动(其实已经被内部消化了)。在这种情况下,onScrolled(RecyclerView recyclerView, int dx, int dy) 是不会被调用的!那什么情况下算是没有更多元素可以滚动呢?

    做个实验好咯

    刷新时加载的数据分别设置为 1、2、3 条,在 logcat 观察onScrolled(RecyclerView recyclerView, int dx, int dy) 是否被调用。

    1. 当屏幕中的 item 数量多到超出屏幕的时候,这时候的滚动是会触发 onScrolled(RecyclerView recyclerView, int dx, int dy) 方法的。

    2. 屏幕中的 item 完全显示在屏幕中时,onScrolled(RecyclerView recyclerView, int dx, int dy) 是不会被触发的。

    附上 HVEndlessRecyclerView 地址

    写在最后

    简诗

    相关文章

      网友评论

      • 没风的地方:写的不错,还会写骚骚的诗词
        HelloVass:@没风的地方 哈哈哈,感谢感谢,好久之前写的了,其实这个问题早就解决了,只是好久没玩儿简书了,在我的 github 上,meizhi 那个库里,我用 kt 重写了一个外国友人的库,应该是在 noloadmoe 包下,有兴趣可以点个star哦,阿里嘎多
      • 德古拉伯爵_694b:分析有鸟用啊,解决方法呢
      • TMAC_EAH:想让他调用怎么办呢~
      • BobEve:那最后有解决办法监听到item不足一屏时的滑动方向么?
        gai_deng:请问又找到解决方法吗?同类问题

      本文标题:RecyclerView,你为什么不回调 onScrolled

      本文链接:https://www.haomeiwen.com/subject/riblhttx.html