RecyclerView滚动与加载同时触发时崩溃问题求助
解决RecyclerView滚动加载时"cannot call this method while RecyclerView is computing a layout or scrolling"错误
问题分析
你遇到的这个错误是RecyclerView的典型冲突场景:当它正在计算布局或者处于滚动状态时,直接调用Adapter的通知方法会打断它的内部流程,进而触发崩溃。大屏手机(比如三星S8)因为单屏能显示更多列表项,滚动时触发加载更多的时机更频繁,所以更容易碰到这个问题。
另外你的代码里还有两个容易被忽略的小问题:
- 调用
NotifyItemRangeChanged的参数逻辑错误:你是要新增item,但这个方法是用来通知已有item发生变化的,应该用NotifyItemRangeInserted;而且起始位置和数量的计算也不对,起始位置应该是旧的item总数,数量是新增的item数(新总数 - 旧总数)。 - 没有防重复加载机制:滚动过程中可能多次触发
LoadMoreEvent,导致重复调用LoadMoreItems,进一步加剧布局冲突。
解决方案
下面是针对你的代码的具体修复步骤:
1. 添加加载状态标志位
在你的Activity类中添加一个布尔变量,用来标记当前是否正在加载,避免重复触发加载逻辑:
private bool isLoading = false;
2. 修改滚动监听器的核心逻辑
更新LoadMoreEvent的回调逻辑,用RecyclerView的Post方法把通知操作延迟到主线程队列中执行(等RecyclerView完成当前布局/滚动后再处理),同时修正通知方法的参数,并加入加载状态判断:
var onScrollListener = new XamarinRecyclerViewOnScrollListener(mLayoutManager); onScrollListener.LoadMoreEvent += (object sender, EventArgs e) => { // 防止重复加载 if (isLoading) return; isLoading = true; int oldCount = loadPhotos.pictures.Count; loadPhotos.LoadMoreItems(3); int newItemsCount = loadPhotos.pictures.Count - oldCount; // 使用Post方法延迟执行通知,避开RecyclerView的布局/滚动流程 mRecyclerView.Post(() => { // 新增item用NotifyItemRangeInserted更精准,性能也更好 mAdapter.NotifyItemRangeInserted(oldCount, newItemsCount); // 加载完成后重置状态 isLoading = false; }); }; mRecyclerView.AddOnScrollListener(onScrollListener);
3. 为什么这样修复有效?
mRecyclerView.Post(...)会把传入的操作放到主线程的消息队列里,等RecyclerView完成当前的布局或滚动任务后再执行,从根源上避免了直接在滚动回调中调用通知方法的冲突。NotifyItemRangeInserted是RecyclerView专门为新增item设计的通知方法,比NotifyItemRangeChanged更贴合你的场景,也能让RecyclerView更高效地更新布局。- 加载状态标志位
isLoading可以防止在一次加载完成前多次触发加载逻辑,避免重复添加item和重复调用通知方法。
额外优化建议
如果你的LoadMoreItems是异步操作(比如从网络加载图片资源),记得要把通知和状态重置逻辑放到异步操作完成后执行,示例如下:
onScrollListener.LoadMoreEvent += async (object sender, EventArgs e) => { if (isLoading) return; isLoading = true; int oldCount = loadPhotos.pictures.Count; // 假设LoadMoreItems是异步方法 await loadPhotos.LoadMoreItemsAsync(3); int newItemsCount = loadPhotos.pictures.Count - oldCount; mRecyclerView.Post(() => { mAdapter.NotifyItemRangeInserted(oldCount, newItemsCount); isLoading = false; }); };
这样调整后,不管是小屏还是大屏手机,滚动加载功能都能稳定运行了。
内容的提问来源于stack exchange,提问作者innomotion media
相关产品推荐
相关产品推荐

