ListView未滚动触发onScroll的思考

作者: a57ecf3aaaf2 | 来源:发表于2016-05-10 10:27 被阅读2206次

    发现问题

    当我们在处理ListView滚动到底部加载更多时,通常的做法是利用OnScrollListener的onScroll方法,来判断是否滚动到了底部。

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        boolean toBottom = firstVisibleItem + visibleItemCount >= totalItemCount;
        if (toBottom && !isLoading && !isFinish) {
            //...
        }
    }
    

    但是这种做法会引发一系列的问题,比如当初始化ListView,并setOnScrollListener时便会回调onScroll方法,此时得到的结果是已经滚动到了底部,在没有任何数据的情况下给出这样一个结果,会对程序的处理逻辑产生影响。

    看看源码:

    /**
         * Set the listener that will receive notifications every time the list scrolls.
         *
         * @param l the scroll listener
         */
        public void setOnScrollListener(OnScrollListener l) {
            mOnScrollListener = l;
            invokeOnItemScrollListener();
        }
    
        /**
         * Notify our scroll listener (if there is one) of a change in scroll state
         */
        void invokeOnItemScrollListener() {
            if (mFastScroll != null) {
                mFastScroll.onScroll(mFirstPosition, getChildCount(), mItemCount);
            }
            if (mOnScrollListener != null) {
                mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
            }
            onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
        }
    

    也就是说,在setOnScrollListener时便已经回调了onScroll方法。

    解决问题

    大多数情况下,大家都忽略了OnScrollListener中的onScrollStateChanged方法。

       public void onScrollStateChanged(AbsListView view, int scrollState);
    

    该方法有两个入参,第二个参数scrollState有三种状态:

        public static int SCROLL_STATE_IDLE = 0;            //结束滚动
        public static int SCROLL_STATE_TOUCH_SCROLL = 1;    //触摸滚动
        public static int SCROLL_STATE_FLING = 2;           //手指离开屏幕后的滚动状态
    

    此时我们可将焦点定位到 SCROLL_STATE_IDLE,将滚动到底部的判断和处理放在结束滚动之后。

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        switch (scrollState) {
            case SCROLL_STATE_IDLE:
                boolean toBottom = view.getLastVisiblePosition() == view.getCount() - 1;
                if (toBottom && !isLoading && !isFinish) {
                    //...
                }
                break;
        }
    

    这样便可完美解决onScroll的频繁调用,及首次调用的问题;同时,也成功解决了滚动到底部的逻辑判断和处理。

    相关文章

      网友评论

        本文标题:ListView未滚动触发onScroll的思考

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