我是 Flutter 世界和移动应用程序开发的新手,并且正在努力解决如何在整个应用程序中传递用户数据的问题。
我已经尝试了几件事,但似乎没有一个很好,我确信我应该遵循一些最佳实践模式。
因为它使示例更容易,所以我使用 firebase 进行身份验证。
我目前有一个单独的登录路径。登录后,我希望大多数视图中都有用户模型,用于检查显示内容的权限、在抽屉中显示用户信息等...
Firebase 有一个await firebaseAuth.currentUser();
在您可能需要用户的任何地方调用它是最佳实践吗?如果是这样,拨打此电话的最佳地点在哪里?
The 颤振代码实验室 https://codelabs.developers.google.com/codelabs/flutter-firebase/显示了在允许写入之前对用户进行身份验证的一个很好的示例。但是,如果页面需要检查身份验证以确定要构建的内容,则异步调用不能进入build
method.
初始化状态
我尝试过的一种方法是重写 initState 并启动调用以获取用户。当未来完成时我打电话setState
并更新用户。
FirebaseUser user;
@override
void initState() {
super.initState();
_getUserDetail();
}
Future<Null> _getUserDetail() async {
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}
这工作得不错,但对于每个需要它的小部件来说似乎有很多仪式。当屏幕在没有用户的情况下加载时也会出现闪烁,然后在未来完成时随用户更新。
通过构造函数传递用户
这也有效,但需要大量样板文件来让用户通过可能需要访问它们的所有路由、视图和状态。另外,我们不能只做popAndPushNamed
当转换路由时,因为我们无法向其传递变量。我们必须改变类似这样的路线:
Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) => new MyPage(user),
));
继承的小部件
https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1 https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1
这篇文章展示了一个很好的使用模式InheritedWidget
。当我将继承的小部件放置在 MaterialApp 级别时,当身份验证状态更改时,子级不会更新(我确信我做错了)
FirebaseUser user;
Future<Null> didChangeDependency() async {
super.didChangeDependencies();
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}
@override
Widget build(BuildContext context) {
return new UserContext(
user,
child: new MaterialApp(
title: 'TC Stream',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new LoginView(title: 'TC Stream Login', analytics: analytics),
routes: routes,
),
);
}
未来建造者
FutureBuilder 似乎也是一个不错的选择,但似乎每条路线都需要做很多工作。在下面的部分示例中,_authenticateUser()
完成后获取用户和设置状态。
@override
Widget build(BuildContext context) {
return new FutureBuilder<FirebaseUser>(
future: _authenticateUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return _buildProgressIndicator();
}
if (snapshot.connectionState == ConnectionState.done) {
return _buildPage();
}
},
);
}
如果您提供有关最佳实践模式的建议或用于示例的资源链接,我将不胜感激。