Flutter ScrollController路由关闭时断言错误及控制器实例问题
问题根源
你在MyNavigatorObserver中直接通过QuestionBankController()创建了新的控制器实例,这个实例和绑定到QuestionDetailsScreen的控制器完全无关——新实例的ScrollController从未挂载到任何滚动视图上,自然会触发'_positions.isNotEmpty'错误。
解决方案一:通过GetX的Tag获取绑定页面的控制器实例
如果你的QuestionDetailsScreen是用GetX注入控制器的,给实例指定唯一Tag,就能在Observer中精准获取对应实例:
- 在QuestionDetailsScreen中绑定控制器时指定Tag
// 在QuestionDetailsScreen的initState或build方法中 final controller = Get.put(QuestionBankController(), tag: 'question_details'); // 将controller.questionDetailsScrollCtrl绑定到你的ListView/ScrollView
- 修改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
相关产品推荐
相关产品推荐

