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

Flutter中PageController绑定多滚动视图报错问题求助

问题根源

全局AppTabHandlerProvider中的PageController是持久化的,当用户退出登录后,原有的PageView虽被路由移除,但框架未完全解除控制器与旧视图的绑定;重新登录进入新的PageView时,同一个控制器被绑定到新视图,触发ScrollController attached to multiple scroll views断言错误。

解决方案

1. 修正Provider的控制器管理逻辑

修改AppTabHandlerProvider,添加控制器重置方法,在退出登录时销毁旧控制器并创建新实例:

/// # App Tab Handler Provider
///
/// Provides state of BottomNavigationBar.
class AppTabHandlerProvider with ChangeNotifier {
  /// Bottom tab bar index
  int bottomNavigationIndex = 0;

  /// Tab bar controller. A glue between [PageView] and [BottomNavigationBar].
  late PageController pageController;

  AppTabHandlerProvider() {
    _initController();
  }

  void _initController() {
    pageController = PageController(initialPage: bottomNavigationIndex);
  }

  /// 重置控制器(用于退出登录场景)
  void resetController() {
    // 销毁旧控制器
    pageController.dispose();
    // 重置索引
    bottomNavigationIndex = 0;
    // 初始化新控制器
    _initController();
    notifyListeners();
  }

  /// Sets new tab index to change page view
  set setNewPageControllerIndex(int index) {
    if (bottomNavigationIndex != index) {
      bottomNavigationIndex = index;
      pageController.jumpToPage(index);
      notifyListeners();
    }
  }

  /// # System Pop Navigation
  ///
  /// Connects bottom Navigation buttons to system navigation pop button. Fixes
  /// behavior of SystemPopNavigationButton to BottomNavigationButtons.
  Future<bool> systemPopNavigation() async {
    if (bottomNavigationIndex >= 1 && bottomNavigationIndex <= 4) {
      setNewPageControllerIndex = 0;
      return false; // 拦截系统返回,留在当前页面
    } else {
      // 退出应用
      await SystemChannels.platform.invokeMethod("SystemNavigator.pop");
      return true;
    }
  }
}

2. 在退出登录时调用控制器重置

在设置页面的退出登录逻辑中,先重置控制器再导航到登录页:

// 退出登录按钮点击事件
onPressed: () async {
  // 执行登出操作(如清除本地token、用户信息等)
  await yourAuthService.logout();
  
  // 获取全局Provider并重置控制器
  Provider.of<AppTabHandlerProvider>(context, listen: false).resetController();
  
  // 导航到登录页(使用pushReplacement避免返回栈残留)
  Navigator.pushReplacementNamed(context, "/");
}

3. 修正WillPopScope的回调类型

确保onWillPop返回Future<bool>,这是Flutter框架的要求,修改后的systemPopNavigation已适配该返回类型。

原理说明

退出登录时主动销毁旧的PageController并创建新实例,确保重新进入PageView时绑定的是全新控制器,彻底切断与旧视图的关联,避免出现一个控制器绑定多个滚动视图的情况。

内容的提问来源于stack exchange,提问作者Alireza Soltani Neshan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 22:53:08