nukc/LoadMoreWrapper

Cannot call this method while RecyclerView is computing a layout or scrolling

chowaikong opened this issue · 17 comments

我使用 android.support.v4.widget.SwipeRefreshLayout 来对 RecyclerView 下拉刷新数据,在完成刷新后就立刻执行了 LoadMoreWrapper 里面的加载更多,因为我 setListener 了。
我也看到 README 说 LoadMoreWrapper 在数据不足一整个屏幕的时候也会触发加载数据,所以会触发 RecyclerView 这个异常 Cannot call this method while RecyclerView is computing a layout or scrolling, 也就是 RecyclerView 在 onLayout 时 调用了 notify 相关的方法。
不知道作者有没有遇到过这个问题?我在你的 demo 里面操作了同样的步骤,但是奇怪的是并没有触发这个异常,在我的项目里面却触发了,所以想请教一下解决办法。

我添加数据后是用的 notifyItemRangeInserted,不是 notifyDataSetChanged

nukc commented

在还没下拉之前,数据是否足够铺满屏幕?下拉刷新后是使用的 notifyItemRangeInserted ,数据还是不足整个屏幕?
主要信息是:Cannot call this method while RecyclerView is computing a layout or scrolling
那就开始来排错吧,应该不是 scrolling 了,因为 LoadMoreWrapper 加载更多有判断:
LoadMoreAdapter.java#L204

if (newState == RecyclerView.SCROLL_STATE_IDLE && mOnLoadMoreListener != null) {
   //....
   mOnLoadMoreListener.onLoadMore(mEnabled);
}

那可以使用 recyclerView.isComputingLayout() 判断下是否正在计算 layout 。
你可以检查一下是否在下拉刷新 notify 过程中又进行了 notify 。
如果还没有解决,我们再来排查

是足够铺满屏幕的。
添加了 recyclerView.isComputingLayout()会导致刷新后直接滑到底部显示 loading,而实际上并没有加载,只是显示 loading 而已。

另外我发现,使用 notifyItemRangeChanged 通知更新就没有以上的问题了,要看看这两个 notify 代码实现上的差别了。

nukc commented

那麻烦你 debug 一下 LoadMoreAdapter.java#L388
第388行,看是否进入到这里之后由于调用了 notifyItemRemoved(position) 导致的

没有修改 mShouldRemove 的值,或进入 LoadMoreAdapter.this.notifyItemRemoved(position)

nukc commented

如果没有进入那就排除了这个可能性,那么可以在下拉之后,在 onLoadMore 里尝试如下方法

recyclerView.post(new Runnable() {
    @Override
    public void run() {
        // notifyItemRangeInserted()
    }
});

这样会触发这个异常:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder

nukc commented

要怎样复现你说这个错误,或者你是否能提供个 demo 呢?如果可以的话,可以加我 QQ353932158

已加Q

nukc commented

多谢反馈

这个问题我也遇到了,怎么解决的,搞了一天了/(ㄒoㄒ)/~~

nukc commented

@hanqingkai 请先升级到最新版本,触发 Cannot call this method while RecyclerView is computing a layout or scrolling 的根本原因说的很清楚,在 rv 还在 computing a layout 或 scrolling 的时候不应该再次调用 notify ,通常会造成这个原因是上次 notify 后,rv 还没有刷新完毕然后又进行了再次 notify,比如数据刷新 loadmore 没有延时操作,或者连续触发 loadmore (notify)等,这些原因比较常见。
如果是触发 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder ,这个就慢慢 debug,在哪个环节出现了问题。

我搞了一天加载更多,遇到了这个问题,发现需要加个延时操作,所以加载更多的时候一定要调网络接口,不能直接add数据后就调用adapter的更新数据方法

@hanqingkai 可能是你的数据同步问题,之前我使用这个库写测试数据就是直接在 listener 里面 add 数据然后 notify 的,没问题。

@hanqingkai 请先升级到最新版本,触发 Cannot call this method while RecyclerView is computing a layout or scrolling 的根本原因说的很清楚,在 rv 还在 computing a layout 或 scrolling 的时候不应该再次调用 notify ,通常会造成这个原因是上次 notify 后,rv 还没有刷新完毕然后又进行了再次 notify,比如数据刷新 loadmore 没有延时操作,或者连续触发 loadmore (notify)等,这些原因比较常见。
如果是触发 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder ,这个就慢慢 debug,在哪个环节出现了问题。

大佬,这个问题一般都怎么debug?线上有报错,但是却复现不出来

nukc commented

@galaxylei 在你改动数据源的地方和刷新的地方加断点试试