当我试图在应用程序加载时从本地存储读取数据时,我遇到了Ffltter的问题.

我有一个继承的小部件,它保存当前用户的身份验证信息.当应用加载时,我想查看本地存储中的会话令牌.如果会话令牌存在,我想用这些信息更新继承的小部件.

我的屏幕是动态的.如果它知道用户已通过身份验证,则会将用户带到请求屏幕,否则会将用户带到注册屏幕.

我遇到的问题是,我无法从依赖于继承的小部件(我的路由小部件)的小部件(我的路由小部件)的initState()方法更新继承小部件的状态

当应用程序加载和更新继承的小部件时,我如何从本地存储中读取?

运行APP时出错:

flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building _InheritedAuthContainer:
flutter: inheritFromWidgetOfExactType(_InheritedAuthContainer) or inheritFromElement() was called before
flutter: RootState.initState() completed.
flutter: When an inherited widget changes, for example if the value of Theme.of() changes, its dependent
flutter: widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor
flutter: or an initState() method, then the rebuilt dependent widget will not reflect the changes in the
flutter: inherited widget.
flutter: Typically references to inherited widgets should occur in widget build() methods. Alternatively,
flutter: initialization based on inherited widgets can be placed in the didChangeDependencies method, which
flutter: is called after initState and whenever the dependencies change thereafter.

路由小部件(根)

class Root extends StatefulWidget {
  @override
  State createState() => RootState();
}

class RootState extends State<Root> {
  static Map<String, Widget> routeTable = {Constants.HOME: Home()};
  bool loaded = false;
  bool authenticated = false;

  @override
  void initState() {
    super.initState();
    if (!loaded) {
      AuthContainerState data = AuthContainer.of(context);
      data.isAuthenticated().then((authenticated) {
        setState(() {
          authenticated = authenticated;
          loaded = true;
        });
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        initialRoute: '/',
        onGenerateRoute: (routeSettings) {
          WidgetBuilder screen;
          if (loaded) {
            if (authenticated) {
              screen = (context) => SafeArea(
                  child: Material(
                      type: MaterialType.transparency,
                      child: routeTable[routeSettings.name]));
            } else {
              screen = (conext) => SafeArea(
                  child: Material(
                      type: MaterialType.transparency, child: Register()));
            }
          } else {
            screen = (context) => new Container();
          }
          return new MaterialPageRoute(
            builder: screen,
            settings: routeSettings,
          );
        });
  }
}

继承的小部件方法,它判断身份验证并self 更新,从而触发路由小部件的重新渲染

Future<bool> isAuthenticated() async {
    if (user == null) {
      final storage = new FlutterSecureStorage();
      List results = await Future.wait([
        storage.read(key: 'idToken'),
        storage.read(key: 'accessToken'), 
        storage.read(key: 'refreshToken'),
        storage.read(key: 'firstName'),
        storage.read(key: 'lastName'),
        storage.read(key: 'email')
      ]);
      if (results != null && results[0] != null && results[1] != null && results[2] != null) {
        //triggers a set state on this widget
        updateUserInfo(
          identityToken: results[0], 
          accessToken: results[1], 
          refreshToken: results[2],
          firstName: results[3],
          lastName: results[4],
          email: results[5]
        );
      }
    }
    return user != null && (JWT.isActive(user.identityToken) || JWT.isActive(user.refreshToken));
  }

主干道

void main() => runApp(
  EnvironmentContainer(
    baseUrl: DEV_API_BASE_URL,
    child: AuthContainer(
      child: Root()
    )
  )
);

在应用程序加载时判断本地存储并更新保存此信息的继承小部件的正确方法是什么?

推荐答案

实际上,你不能通过initState方法访问InheritedWidget.而是try 从didChangeDependencies访问它.

示例:

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  if (!loaded) {
    AuthContainerState data = AuthContainer.of(context);
    data.isAuthenticated().then((authenticated) {
      setState(() {
        authenticated = authenticated;
        loaded = true;
      });
    });
  }
}

另一种方式是调度具有SchedulerBindinginitState中的数据获取.你可以找到文档here

SchedulerBinding.instance.addPostFrameCallback((_) {
  // your login goes here
});

注意:请记住,只要任何父InheritedWidget的状态或依赖项改变,就会调用didChangeDependencies.请看一下文档here.

希望这能有所帮助!

Flutter相关问答推荐

具有可变高度小部件的SingleChildScrollView内的列

带有可滚动页面(不包括分页区)的Flutter 页面视图

Android Studio中的Ffltter&;Couchbase:进程C:/Program Files/Git/bin/bash以非零退出值35结束

无法在我的Flutter 应用程序中使用GoRouter测试导航

try 使用fl_Chart of Ffltter,但在导入它时遇到以下错误:Error:';TextScaler';is;t a type

Firebase WHERE过滤器在日期字段中不起作用

Flutter守护进程无法启动

构建方法中的性能声明小部件

使用现有Map方法对子类克隆方法的逻辑进行Dart标准化

SliverAppbar 呈蓝色

了解多Provider 和流

如何在flutter中实现这样的底部导航栏?

没有为类型 'Widget' 定义运算符 '[]' .try 定义运算符[]

文本溢出文本框 - Flutter

Riverpod中stateNotiferProvider和notifierProvider的区别

Cloud firestore:如何使用 map 对象创建和更新嵌套数组

Show Snackbar above to showModalBottomSheet Flutter

如何在 Flutter 中将 ScaffoldMessenger 中的 Snackbar 显示为 Widget?

Flutter 如何要求用户在应用程序中设置电话密码?

Flutter:如何将列表转换为字符串?