Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.wid

Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView


今天在使用RecyclerView.notifyDataSetChanged的时候报了这个异常,是数据刷新时间间矩很快的情况下出现的,字面意思是不能在RecyclerView计算布局或者滚动的时候使用这个方法,那么其他的notifyXXX之类的方法也是类似的。


最后翻了下RecyclerView的源码看到了这个方法

/**
 * Returns whether RecyclerView is currently computing a layout.
 * <p>
 * If this method returns true, it means that RecyclerView is in a lockdown state and any
 * attempt to update adapter contents will result in an exception because adapter contents
 * cannot be changed while RecyclerView is trying to compute the layout.
 * <p>
 * It is very unlikely that your code will be running during this state as it is
 * called by the framework when a layout traversal happens or RecyclerView starts to scroll
 * in response to system events (touch, accessibility etc).
 * <p>
 * This case may happen if you have some custom logic to change adapter contents in
 * response to a View callback (e.g. focus change callback) which might be triggered during a
 * layout calculation. In these cases, you should just postpone the change using a Handler or a
 * similar mechanism.
 *
 * @return <code>true</code> if RecyclerView is currently computing a layout, <code>false</code>
 *         otherwise
 */
public boolean isComputingLayout() {
    return mLayoutOrScrollCounter > 0;
}

这个方法注释的意思大致是这样的:

如果此方法返回true,则意味着循环视图处于锁定状态,并尝试更新适配器内容,将导致异常,因为适配器无法更改,而循环视图则试图计算布局。在此状态下,您的代码不太可能会运行,因为当一个布局遍历发生或重新使用时,框架会调用它来响应系统事件(触摸、可访问性等)。如果您有一些自定义逻辑来响应视图回调(例如焦点更改回调),在布局计算过程中可能会触发该事件,则可能会发生这种情况。在这些情况下,您应该使用处理程序或类似的机制来延迟更改。

那么最后处理的方法是先判断这个 是否为true,再进行notifyXXX的操作。中间我是使用的递归实现,大家用handler之类的也是可以的。我的解决方法如下,Kotlin代码:

/**
 * 预搜索返回数据
 * 这里要先解决这个问题
 * java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView
 */
override fun bindPreSearchData(data: List<KeywordBean>) {
    // 这里返回数据后要把数据绑定给对应的view
    if (preSearchRc.isComputingLayout) {
        // 延时递归处理。
        preSearchRc.postDelayed({
            bindPreSearchData(data)
        }, 100)
    } else {
        preDatas?.clear()
        preDatas?.addAll(data)
        preSearchingAdapter?.setKeyword(etSearch.text.toString().trim())
        preSearchingAdapter?.notifyDataSetChanged()
        preSearchRc.visibility = View.VISIBLE
    }
}

记录这个问题希望对自己和大家能有所帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值