【发布时间】:2019-10-31 07:32:13
【问题描述】:
我基本上是在寻找一种方法来开始加载数据或导航到登录屏幕。
FutureProvider 从 SharedPreferences 获得它的价值。默认主屏幕只是一个带有微调器的徽标。
如果用户 ID 解析为 null,则应用应导航到登录屏幕,否则应调用将开始加载数据的方法,然后在完成后导航到主页。
这可以通过 FutureProvider 实现吗?
我将它添加到页面构建中以确保页面小部件将订阅提供者:
Widget build(BuildContext context) {
userInfo = Provider.of<UserInfo>(context);
print('Building with $userInfo');
return PageWithLoadingIndicator();
....
我将它添加到 didChangeDependencies 以对更改做出反应:
@override
void didChangeDependencies() {
print('Deps changed: $userInfo');
super.didChangeDependencies();
// userInfo = Provider.of<UserInfo>(context); // Already building, can't do this.
// print('And now: $userInfo');
if (userInfo == null) return;
if (userInfo.userId != null) {
startUp(); // Run when user is logged in
} else {
tryLogin(); // Navigate to Login
}
}
因为我不能在 initState 中使用 Provider.of,所以我添加了一个 PostFrameCallback
void postFrame(BuildContext context) {
print('PostFrame...');
userInfo = Provider.of<UserInfo>(context);
}
Main 非常简单——它现在只是用一个 FutureProvider 设置 MultiProvider。
class MyApp extends StatelessWidget {
Future<UserInfo> getUserInfo() async {
String token = await UserPrefs.token;
return UserInfo.fromToken(
token,
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'App One',
theme: ThemeData(
primarySwatch: Colors.purple,
),
home: MultiProvider(
providers: [FutureProvider<UserInfo>(builder: (_) => getUserInfo())],
child: LoadingScreen(),
),
);
}
}
问题在于,现在我可以从打印语句中看到“didChangeDependencies”被调用了两次,但 userInfo 的值始终为 null,即使 build() 最终获得了 UserInfo 的实例,如在 build() 方法中打印语句。
我猜我可以在 build 方法中添加一些逻辑,但这让我觉得做错了地方......也许它没有我想的那么糟糕?
【问题讨论】:
-
您是否尝试调用 userInfo = Provider.of
(context);在 didChangeDependencies 中? -
是的,你不能那样做。它会导致错误,因为 Build 已经在进行中。
-
我认为问题在于Provider只想构建Widgets,而不是控制应用程序的流程。因此,现在在 initState 的这个页面上,我添加了一个对异步函数的调用,该函数将等待 sharedPreferences,然后导航离开或开始数据加载过程。
标签: flutter dependency-injection state