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

Flutter ScrollController路由关闭时断言错误及控制器实例问题

解决ScrollController未关联滚动视图的问题(GetX + NavigatorObserver场景)

问题根源

你在MyNavigatorObserver中直接通过QuestionBankController()创建了新的控制器实例,这个实例和绑定到QuestionDetailsScreen的控制器完全无关——新实例的ScrollController从未挂载到任何滚动视图上,自然会触发'_positions.isNotEmpty'错误。

解决方案一:通过GetX的Tag获取绑定页面的控制器实例

如果你的QuestionDetailsScreen是用GetX注入控制器的,给实例指定唯一Tag,就能在Observer中精准获取对应实例:

  1. 在QuestionDetailsScreen中绑定控制器时指定Tag
// 在QuestionDetailsScreen的initState或build方法中
final controller = Get.put(QuestionBankController(), tag: 'question_details');
// 将controller.questionDetailsScrollCtrl绑定到你的ListView/ScrollView
  1. 修改MyNavigatorObserver的didPop方法
class MyNavigatorObserver extends NavigatorObserver {
  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    if (route.settings.name == "/questiondetailsscreen") {
      Future.delayed(Duration.zero, () {
        // 获取绑定到该页面的控制器实例
        final controller = Get.find<QuestionBankController>(tag: 'question_details');
        controller.fireWhenCloseQuestionDetails();
        // 页面关闭后删除该Tag的实例,避免内存泄漏
        Get.delete<QuestionBankController>(tag: 'question_details');
      });
    }
  }
}

解决方案二:直接在页面dispose时调用方法(更简洁推荐)

页面关闭时会自动触发dispose,直接在这里调用目标方法,完全避免实例匹配问题:

class QuestionDetailsScreen extends StatefulWidget {
  @override
  _QuestionDetailsScreenState createState() => _QuestionDetailsScreenState();
}

class _QuestionDetailsScreenState extends State<QuestionDetailsScreen> {
  late QuestionBankController controller;

  @override
  void initState() {
    super.initState();
    controller = Get.put(QuestionBankController());
  }

  @override
  void dispose() {
    // 页面关闭时直接调用方法
    controller.fireWhenCloseQuestionDetails();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        controller: controller.questionDetailsScrollCtrl,
        // 页面其他内容
      ),
    );
  }
}

控制器代码优化(避免冗余初始化与报错)

修改QuestionBankController,去掉冗余的ScrollController初始化,并增加安全判断:

class QuestionBankController extends GetxController {
  late ScrollController questionDetailsScrollCtrl;

  @override
  void onInit() {
    super.onInit();
    questionDetailsScrollCtrl = ScrollController();
    questionDetailsScrollCtrl.addListener(_onScroll);
  }

  void _onScroll() {
    print("Scroll position: ${questionDetailsScrollCtrl.position.pixels}");
  }

  void fireWhenCloseQuestionDetails() {
    print("Fire");
    // 先判断控制器是否还关联滚动视图,防止报错
    if (questionDetailsScrollCtrl.hasClients) {
      print(questionDetailsScrollCtrl.position.pixels);
    } else {
      print("ScrollController已断开关联");
    }
  }

  @override
  void onClose() {
    print("On close");
    questionDetailsScrollCtrl.dispose();
    super.onClose();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:57:45