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

调用notifyListeners后Widget未重建,登录后无法访问NavigationRail全部页面

问题分析与解决方案

核心问题

你在login函数中新建了一个独立的LoginProvider实例,而UI层(main.dart)监听的是ChangeNotifierProvider创建的另一个实例。两者完全独立,所以调用notifyListeners()只会通知这个新实例的监听者,不会触发UI层的重建。

修改步骤

1. 提升Provider的作用域

把ChangeNotifierProvider移到MyHomePage之外,确保整个应用中只有一个LoginProvider实例,避免每次build时重建Provider。

修改main.dart的根组件部分:

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => LoginProvider(),
      child: const MyApp(),
    ),
  );
}

// 保留原MyApp和MyHomePage结构,移除MyHomePage内部的ChangeNotifierProvider

2. 在login函数中获取全局的Provider实例

不要新建LoginProvider,而是通过Provider.of获取已存在的实例。修改login.dart中的login函数:

void login(String userName, String passWord, BuildContext context) async {
  Response response;
  Dio dio = Dio();

  dio.interceptors.add(InterceptorsWrapper(
    onResponse: (response, handler) {
      var token = getToken.Transcribe(response.data);

      // 获取全局的LoginProvider实例,listen: false表示仅修改状态不监听
      final loginProvider = Provider.of<LoginProvider>(context, listen: false);
      loginProvider.providestate(true);

      print(token);
      print("logged in");

      handler.next(response);
    },
  ));

  try { 
    // Http Post method
  } catch (e) {
    print(e);
  }
}

注意:调用login时需要传入能找到Provider的BuildContext(比如从登录页面的按钮点击事件中获取)。

3. 调整MyHomePage中的NavigationRail代码

移除MyHomePage内部的ChangeNotifierProvider,直接使用全局的Provider:

class MyHomePageState extends State<MyHomePage> {
  var selectedIndex = 0;
  List<Widget> pages = [Page0(), Page1(), Page2(), Placeholder()];

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return Scaffold(
        body: Row(
          children: [
            SafeArea(
              child: Consumer<LoginProvider>(
                builder: (context, provider, child) {
                  return NavigationRail(
                    extended: constraints.maxWidth >= 600,
                    minExtendedWidth: 200,
                    destinations: const [
                      NavigationRailDestination(icon: Icon(Icons.home), label: Text("首页")),
                      NavigationRailDestination(icon: Icon(Icons.pageview), label: Text("页面1")),
                      NavigationRailDestination(icon: Icon(Icons.pageview), label: Text("页面2")),
                      NavigationRailDestination(icon: Icon(Icons.settings), label: Text("设置")),
                    ],
                    selectedIndex: selectedIndex,
                    onDestinationSelected: (value) {
                      if (provider.loginstate) {
                        setState(() {
                          selectedIndex = value;
                        });
                        print("On");
                      } else {
                        if (value == 0 || value == 3) {
                          setState(() {
                            selectedIndex = value;
                          });
                          print("OFF");
                        }
                      }
                    },
                  );
                },
              ),
            ),
            Expanded(
              child: Scaffold(
                body: IndexedStack(
                  index: selectedIndex,
                  children: pages,
                ),
              ),
            ),
          ],
        ),
      );
    });
  }
}

额外注意事项

  • 确保调用login时传入的BuildContext处于Provider的作用域内。
  • 如果需要在无上下文环境访问Provider,可以使用GlobalKey来获取应用级上下文。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:35:26