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

Flutter:移除isScrollingNotifier监听器致崩溃,需移除吗?原因何在?

问题分析与解决:ScrollController dispose时访问position导致崩溃

崩溃原因

崩溃的核心问题在于:当从新页面返回原页面时,原页面的ListView会先于State的dispose方法被销毁,此时ScrollController已经和滚动视图解绑,scrollController.position这个 getter 内部会触发断言检查_positions.isNotEmpty,而此时_positions是空列表,直接触发了断言错误。

你之前的逻辑没问题——添加监听器后确实需要在dispose时移除,但问题出在移除监听器前获取position的操作,此时控制器已经没有绑定的滚动视图了,所以这一步直接炸了。

解决方案

方案一:判断控制器是否有绑定的position再移除监听器

修改dispose方法,先检查scrollController.positions是否非空,再执行移除操作:

@override
void dispose() {
  print("dispose");
  // 先判断控制器是否还有绑定的滚动视图位置
  if (scrollController.positions.isNotEmpty) {
    scrollController.position.isScrollingNotifier.removeListener(handleScrollStartStop);
  }
  print("disposed GODVC 2");
  scrollController.removeListener(handleScrolled);
  print("disposed GODVC 3");
  scrollController.dispose();
  print("disposed GODVC 4");
  super.dispose();
}

方案二:改用ScrollNotification监听滚动状态

这种方式不需要直接操作ScrollController的position,更安全:
把原页面的body部分替换为以下代码:

body: NotificationListener<ScrollNotification>(
  onNotification: (notification) {
    if (notification is ScrollStartNotification) {
      print('Scroll started');
    } else if (notification is ScrollEndNotification) {
      print('Scroll stopped');
    }
    return false; // 允许事件继续传递
  },
  child: ListView.builder(
    controller: scrollController,
    itemBuilder: ((context, index) {
      return ListTile(
        title: Text("$index. Something"),
        onTap: () {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) => MyHomePage(
                viewNumber: widget.viewNumber + 1,
              ),
            ),
          );
        },
      );
    }),
  ),
),

同时可以删掉initState中对isScrollingNotifier的监听,以及dispose中对应的移除代码。

总结

你对监听器的管理思路是正确的,只是忽略了控制器和滚动视图解绑的时机——dispose执行时,滚动视图可能已经销毁,控制器不再持有任何position。通过提前判断或改用更安全的监听方式,就能解决这个崩溃问题。

内容的提问来源于stack exchange,提问作者sudoExclamationExclamation

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:40:19