【问题标题】:Can Flutter Router Navigator and Provider at top level work together?顶层的 Flutter Router Navigator 和 Provider 可以一起工作吗?
【发布时间】:2020-05-26 00:56:52
【问题描述】:

我在使用 Providers 和导航器的状态管理时遇到了一个大问题。

我们必须知道的事情:

1) 我的 RESTFUL API 提供了一个在 12 小时到期的令牌。

2) 我的主页:如果用户已通过身份验证,则参数是有条件的。如果没有,我必须根据其他参数决定哪个屏幕必须是主页。

3) 如果我在一个屏幕上并且令牌在应用程序对 API 执行的任何请求时过期,我:

  • 在我的auth 提供程序中调用一个执行注销程序的函数(我用令牌清理localStorage)。这个auth 提供程序将一个名为isAuth 的属性设置为false
  • isAuth 为false 时,如果您查看main.dart 文件home:,您会看到将显示LoginPage()

这里的一切都很好。问题是当我必须使用Navigator.of... 进行重定向时。例如,如果令牌过期错误,我会这样做:Navigator.popUntil(context, ModalRoute.withName('/login')); 应用程序毫无问题地转到LoginPage(),但是......当我尝试使用登录(使用auth 提供程序的login 功能)它停留在登录页面上!如果我在任何地方使用Navigator 去任何其他地方,它似乎会覆盖我用来控制哪个页面显示为home 的“状态管理方式”。

你能帮帮我吗?

我的main.dart 代码:

// Providers
import 'package:provider/provider.dart';
import 'package:cadsanjuan_movil/providers/auth.dart';

// Pages
import './pages/login_page.dart';
import './pages/initial_loading_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  final storage = new FlutterSecureStorage();
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider<Auth>(create: (context) => Auth()),
          ChangeNotifierProvider<TurnActive>(create: (context) => TurnActive()),
          ChangeNotifierProxyProvider<TurnActive, Checkup>(
              create: (context) => Checkup(),
              update: (_, turnActive, checkup) {
                checkup.turnData = turnActive.turnData;
                return checkup;
              }),
          ChangeNotifierProxyProvider<Auth, ErrorProvider>(
              create: (context) => ErrorProvider(),
              update: (_, auth, errorProvider) {
                errorProvider.logoff = auth.logoff;
                return errorProvider;
              }),
        ],
        child: Consumer3<Auth, TurnActive, Checkup>(
          builder: (context, auth, turnActive, checkup, _) {
            return MaterialApp(
              title: 'CAD App',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              home: auth.isAuth
                  ? (turnActive.turnData != null &&
                          turnActive.turnData['turn']['checkUpStartId'] != null)
                      ? CheckupPage() // Si el cotejo está en proceso
                      : InitialLoadingPage() // Si no hay cotejo iniciado
                  : FutureBuilder(
                      // Si estamos no hay autenticación en el estado, se chequea en el localStorage
                      future: auth.tryAutoLogin(),
                      builder: (ctx, authResultSnapshot) =>
                          authResultSnapshot.connectionState ==
                                  ConnectionState.waiting
                              ? LoadingData()
                              : LoginPage(),
                    ),
              routes: {
                LoginPage.routeName: (context) => LoginPage(),
                InitialLoadingPage.routeName: (context) => InitialLoadingPage(),
                CheckupPage.routeName: (context) => CheckupPage(),
                CheckupGroupsPage.routeName: (context) => CheckupGroupsPage(),
              },
            );
          },
        ));
  }
}

【问题讨论】:

标签: flutter state router provider state-management


【解决方案1】:

问题出在:

Navigator.popUntil(context, ModalRoute.withName('/login'))

如果我们推送 "/login" 这会覆盖 MaterialApp 中的 home 参数,加载登录页面但页面不会因为路由而弹出。正确的做法是:

Navigator.of(context)
          .pushNamedAndRemoveUntil('/', (Route<dynamic> route) => false);

通过这个我们重定向到'/',然后使用home参数的状态管理将起作用。

【讨论】:

    猜你喜欢
    • 2020-02-24
    • 2020-01-13
    • 1970-01-01
    • 2013-07-09
    • 2016-01-29
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多