我已经编写了一个需要身份验证的应用程序。我还将持久身份验证数据安全地保存在设备上,因此不需要在每次启动应用程序时手动登录。
应用程序启动后,它将自动路由到主路由(在我的情况下,这是无状态启动屏幕)。执行以下代码:
@override
Widget build(BuildContext context) {
ifLoggedIn(context);
return Scaffold(
body: Center(
child: Image.asset("assets/logo-sm.png", width: 200,),
),
);
}
void ifLoggedIn(context) async {
if (User.user != null) { // in case of a hot reload resetting the damn app
Navigator.of(context).push(right(PublicStart()));
} else {
User user = await User.loginFromSafeStorage(context); // login from safe storage
if (user != null)
Navigator.of(context).push(right(PublicStart()));
else // nope, no credentials found, redirect to the start-screen
Navigator.of(context).push(up(SignInScreen()));
}
}
ifLoggedIn(context)
函数是一个异步函数,用于检查登录数据是否已经存储在本地。在这种情况下,它将对用户进行身份验证。
此过程如下:
Case: Logindata found -> Login user and navigate to the start-screen
Case: No logindata found -> Navigate to the sign-in-screen.
如您所见,由于此函数是异步的,因此返回下面的Scaffold
并且该无状态窗口小部件的构建过程不会中断。但是...
显然,在构建此小部件期间调用了setState。我不知道如何或为什么,但是似乎发生了。我已经尝试解决此问题,但这不是第一次发生,而且我对在此应用程序的开发中采用不良做法感到难过。
我怀疑这与登录用户的检查有关。
另一个随机发生的错误(我的意思是很多)是:
Unhandled Exception: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line <insert number> pos <insert number>: '!_debugLocked': is not true.
,其中的数字不时变化。据我了解,这是为了防止路由被多次调用或破坏与路由有关的任何事情。由于我是在随机时间收到此错误的,因此这必须与异步函数有关。
最后确定我的问题: 我在这里做错了什么?做上述事情的规范是什么?
答案 0 :(得分:1)
编辑(更多说明):
不得从build方法中触发异步调用,因为由于不同的原因可以多次调用它(build方法),因此您不希望代码执行多次,因为这会导致不良结果>
解决方案是使用有状态的小部件并执行必须从那里运行一次的代码(在您的情况下为检查身份验证状态的代码)(最好从initState()
开始)
还请查看此answer