Android --- RecyclerViwe中使用SnapHelper报错:“An instance of OnFlingListener already set

首先来了解一个概念,手指在屏幕上滑动RecyclerView然后松手,RecyclerView中的内容会顺着惯性继续往手指滑动的方向继续滚动直到停止,这个过程叫做Fling。Fling操作从手指离开屏幕瞬间被触发,在滚动停止时结束。而OnFlingListener显然就是监听Fling滚动事件的监听器。

4.原因重点:(SnapHelper被多次创建并绑定到同一个RecyclerView)


通常我们在做RecyclerView的嵌套时总会遇到这样的问题,是因为每次在onBindViewHolder中都这样写:


SnapHelper snapHelper = new PagerSnapHelper()

snapHelper.attachToRecyclerView(recyclerView)



每次滑动RecyclerView都需要重新创建SnapHelper对象并将其附着到RecyclerView上,导致一个RecyclerIView会绑定多个SnapHelper,在回头绘制RecyclerView时,会发现一个RecyclerView的SnapHelper实例(多个)重复设置,导致滚动事件出问题而退出滚动,致使整个app应用崩溃退出!

5.解决方法


5.1第一种方法:

在重新绘制RecyclerView时首先移除创建的前一个SnapHelper实例的OnFlingListener监听器。

Tips:也就是RecyclerView在第二次滑动到该位置时

Java语言


 SnapHelper snapHelper = new PagerSnapHelper()

 recycleView.setOnFlingListener(null)

 snapHelper.attachToRecyclerView(recyclerView)



Kotlin语言


val snapHelper: SnapHelper = PagerSnapHelper()

recycleView.onFlingListener = null

snapHelper.attachToRecyclerView(recyclerView)



Tips:SnapHelper通过attachToRecyclerView()方法附着到RecyclerView上,从而实现辅助RecyclerView滚动对齐操作。

5.2第二种方法:

将SnapHelper snapHelper = new

PagerSnapHelper()放在全局定义(针对类),允许类中只存在一个SnapHelper对象。每次重新绘制RecyclerView时总是调用该SnapHelper实例对象的onFlingListener。

Tips:此方法不用添加任何代码,仅需要将SnapHelper snapHelper = new

PagerSnapHelper()放在与重写方法onBindViewHolder()同级的位置。

6原理剖析


据下面的源码可以看到当与RecyclerView绑定的SnapHelper实例对象的OnFlingListener已经被设置时,再次设置系统会抛出异常:”An instance of OnFlingListener already set.“

7源码解析:



错误类型&具体错误:IllegalArgumentException:An instance of OnFlingListener already set.




 /**

     * Attaches the {@link SnapHelper} to the provided RecyclerView, by calling

     * {@link RecyclerView#setOnFlingListener(RecyclerView.OnFlingListener)}.

     * You can call this method with {@code null} to detach it from the current RecyclerView.

     *

     * @param recyclerView The RecyclerView instance to which you want to add this helper or

     *                     {@code null} if you want to remove SnapHelper from the current

     *                     RecyclerView.

     *

     * @throws IllegalArgumentException if there is already a {@link RecyclerView.OnFlingListener}

     * attached to the provided {@link RecyclerView}.

     *

     */




/**

     * Called when an instance of a {@link RecyclerView} is attached.

     */

    private void setupCallbacks() throws IllegalStateException {

        if (mRecyclerView.getOnFlingListener() != null) {

            throw new IllegalStateException("An instance of OnFlingListener already set.");

        }

        mRecyclerView.addOnScrollListener(mScrollListener);

        mRecyclerView.setOnFlingListener(this);

    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值