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

使用Dismissible与Provider时动画卡顿问题求助

解决Dismissible滑动删除时Provider.notifyListeners()导致的动画卡顿问题

核心问题是:滑动删除时,notifyListeners()会立即触发UI重建,和Dismissible的动画帧渲染抢占UI线程,导致掉帧卡顿。下面是几个实用的解决办法:

1. 延迟到Dismissible动画完成后再调用notifyListeners()

Dismissible提供了onDismissed回调,这个回调会在滑动动画完全结束后触发。你可以把数据移除和状态通知拆分:

  • 修改Provider中的deleteNotebook方法,只做数据移除,暂时不通知:
void deleteNotebook(String id) {
  _notebooks.removeWhere((item) => item.id == id);
  // 这里先不调用notifyListeners()
}
  • 在Dismissible的onDismissed里完成数据删除后,再调用通知:
Dismissible(
  key: Key(object.id),
  onDismissed: (direction) {
    final provider = Provider.of<NMyProvider>(context, listen: false);
    provider.deleteNotebook(object.id);
    // 动画结束后再通知UI更新
    provider.notifyListeners();
  },
  child: YourCardWidget(),
)

这样动画先流畅完成,再触发UI重建,完全避免了两者的线程冲突。

2. 缩小Provider的监听范围,减少不必要的重建

如果你的页面有很多非列表内容,notifyListeners()会触发整个页面的重建,加重性能负担。可以用Consumer或者select来只重建需要更新的列表部分:

比如用Consumer包裹列表:

Consumer<NMyProvider>(
  builder: (context, provider, child) {
    return ListView.builder(
      itemCount: provider.notebooks.length,
      itemBuilder: (context, index) {
        final item = provider.notebooks[index];
        return Dismissible(
          // ... Dismissible配置
        );
      },
    );
  },
)

这样即使调用notifyListeners(),也只会重建列表区域,其他UI不受影响,能显著降低卡顿概率。

3. (可选)用AnimatedList替代普通ListView

如果需要列表删除的过渡动画和Dismissible配合,AnimatedList可以和Provider更好地协同。不过这个方案需要调整列表的构建逻辑,适合对动画效果有更高要求的场景。

内容的提问来源于stack exchange,提问作者Gaëtan GR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:57:37