【问题标题】:Flutter: Provider was used after being disposedFlutter: Provider 被处理后被使用
【发布时间】:2021-05-29 04:27:05
【问题描述】:

我正处于完成一个相当大的项目的最后阶段,现在面临供应商的一个新问题。到目前为止,我已经阅读了有关此主题的几乎所有可用问题,但仍然无法找到解决方案。

我有两个 ChangeNotifier 模型,分别是:AuthProviderUserProvider。 当我尝试从另一个推送的路由(设置页面)调用“authProvider.logout()”时,会发生有问题的错误,该路由按预期工作,但抛出了一个错误

UserProvider 被销毁后被使用。

AuthProvider 是在 MaterialApp 之上通过以下方式创建的:

MultiProvider(
        providers: [
          ChangeNotifierProvider<AuthProvider>(
            create: (BuildContext context) => AuthProvider.instance(),
          ),
          ...
        ],
        child: MaterialApp(
          home: MainPage(),
        ),
      ),

MainPage 使用 switch 语句根据来自 AuthProvider 的值显示 LoginScreen 或 HomeScreen。

@override
  Widget build(BuildContext context) {
    final AuthStatus authStatus = context.select<AuthProvider, AuthStatus>(
      (AuthProvider auth) => auth.status,
    );
    switch (authStatus) {
      case AuthStatus.NOT_LOGGED_IN:
        ...
      case AuthStatus.LOGGED_IN:
        return MultiProvider(
                    providers: <SingleChildWidget>[
                      ChangeNotifierProvider<UserModel>(
                        create: (BuildContext context) => UserModel(),
                        lazy: false,
                      ),
                      ...
                    ],
                    child: const HomeScreen(),
                  );
        break;
      default:
        ...
    }
  }

从主屏幕上方的 MainPage 中初始化 UserProvider。

MultiProvider(
  providers: <SingleChildWidget>[
     ChangeNotifierProvider<UserProvider>(
        create: (BuildContext context) => UserProvider(),
        lazy: false,
     ),
     ...
  ],
  child: const HomeScreen(),
);

我从 HomeScreen 内部推送设置页面,显示 UserProvider 和 AuthProvider 的现有值。

final AuthProvider authProvider = Provider.of<AuthProvider>(context);
final UserProvider userModel = Provider.of<UserProvider>(context);
Navigator.push(
  context,
  PageTransition<SettingsPage>(
    child: MultiProvider(
      providers: <ChangeNotifierProvider<dynamic>>[
        ChangeNotifierProvider<AuthProvider>.value(
          value: authProvider,
        ),
        ChangeNotifierProvider<UserProvider>.value(
          value: userProvider,
        ),
      ],
      child: SettingsPage(),
      ),
      type: PageTransitionType.leftToRightWithFade,
   ),
);

最后,我在 SettingsPage 中有一个简单的 logoutCallback,它与其他逻辑一起更改身份验证状态的值,因此(预期)导致 LoginPage 再次显示。

SettingsButton(
 title: 'Logout',
 callback: () {
   Provider.of<AuthProvider>(ctx, listen: false).logoutCallback();
   Navigator.of(ctx).pop();
}),

预期的行为是在 logoutCallback() 中更改了 authStatus 的值,并且当弹出 SettingsPage 时,由于 switch 语句,HomeScreen 将被 LoginPage 替换。 尽管发生了这种情况,但我收到了一个很长的错误: [A UserProvider被暴露后被使用][1] [1]:https://i.stack.imgur.com/oeyor.png

任何帮助将不胜感激,因为我不再确定可能导致此错误的原因。 如果我应该包含更多信息或代码中的特定示例,请告诉我。

【问题讨论】:

  • 我在一个应用程序中看到了这种问题,其中 stck 没有被正确管理。因此,基于另一个屏幕的contextProvider 的实例仍然存在。一旦旧屏幕被移除,它就修复了错误

标签: flutter flutter-provider


【解决方案1】:

在您提供的以下代码 sn-p 中,logoutcallback() 可能是一个异步函数并且需要一些时间来执行。甚至在执行完成之前,小部件就会从树中删除。

SettingsButton(
 title: 'Logout',
 callback: () {
   Provider.of<AuthProvider>(ctx, listen: false).logoutCallback();
   Navigator.of(ctx).pop();
}),

您可以做的是使用then() 或使用async await 链接这两种方法。

【讨论】:

  • 感谢您的建议。但是,logoutCallback 不是 Future。
  • 它是否调用了 API?还是从本地内存中删除令牌?
  • 它调用 FirebaseAuth 注销(这是未来),但不管它断言身份验证状态值。我相当肯定这不是注销功能失败,因为它按预期工作。但正如@FloydWatson 所提到的,这很可能是由于堆栈管理不善。 UserProvider 被过早释放,导致错误。
猜你喜欢
  • 2021-01-23
  • 2020-03-12
  • 1970-01-01
  • 2021-11-16
  • 2022-11-16
  • 2020-11-10
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
相关资源
最近更新 更多