You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:31:24