gpt4 book ai didi

Flutter - 如何将用户数据传递给所有 View

转载 作者:IT老高 更新时间:2023-10-28 13:49:32 27 4
gpt4 key购买 nike

我是 Flutter 世界和移动应用程序开发的新手,并且正在为如何在我的应用程序中传递用户数据而苦恼。

我尝试了几件事,但没有一个看起来很好,我确信我应该遵循一些最佳实践模式。

因为它使示例更容易,我使用 firebase 进行身份验证。我目前有一个单独的登录路径。登录后,我希望大多数 View 中的用户模型用于检查显示内容的权限、在抽屉中显示用户信息等...

Firebase 有一个 await firebaseAuth.currentUser(); 最佳做法是在您可能需要用户的任何地方调用它吗?如果是这样,调用电话的最佳地点在哪里?

flutter codelab显示了在允许写入之前验证用户的一个很好的例子。但是,如果页面需要检查 auth 以确定要构建的内容,则异步调用无法进入 build 方法。

初始化状态

我尝试过的一种方法是覆盖 initState 并启动调用以获取用户。当 future 完成时,我调用 setState 并更新用户。

    FirebaseUser user;

@override
void initState() {
super.initState();
_getUserDetail();
}

Future<Null> _getUserDetail() async {
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}

这很不错,但对于每个需要它的小部件来说似乎都是一种仪式。当屏幕在没有用户的情况下加载时也会闪烁,然后在未来完成时与用户一起更新。

通过构造函数传递用户

这也是可行的,但需要大量样板来让用户通过可能需要访问它们的所有路由、 View 和状态。此外,我们不能在转换路由时只执行 popAndPushNamed,因为我们不能将变量传递给它。我们必须改变类似这样的路线:

Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) => new MyPage(user),
));

继承的小部件

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

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();
}
},
);
}

对于最佳实践模式或用于示例的资源链接的任何建议,我将不胜感激。

最佳答案

我建议进一步研究继承的小部件;下面的代码展示了如何使用它们来异步更新数据:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
runApp(new MaterialApp(
title: 'Inherited Widgets Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Inherited Widget Example'),
),
body: new NamePage())));
}

// Inherited widget for managing a name
class NameInheritedWidget extends InheritedWidget {
const NameInheritedWidget({
Key key,
this.name,
Widget child}) : super(key: key, child: child);

final String name;

@override
bool updateShouldNotify(NameInheritedWidget old) {
print('In updateShouldNotify');
return name != old.name;
}

static NameInheritedWidget of(BuildContext context) {
// You could also just directly return the name here
// as there's only one field
return context.inheritFromWidgetOfExactType(NameInheritedWidget);
}
}

// Stateful widget for managing name data
class NamePage extends StatefulWidget {
@override
_NamePageState createState() => new _NamePageState();
}

// State for managing fetching name data over HTTP
class _NamePageState extends State<NamePage> {
String name = 'Placeholder';

// Fetch a name asynchonously over HTTP
_get() async {
var res = await http.get('https://jsonplaceholder.typicode.com/users');
var name = json.decode(res.body)[0]['name'];
setState(() => this.name = name);
}

@override
void initState() {
super.initState();
_get();
}

@override
Widget build(BuildContext context) {
return new NameInheritedWidget(
name: name,
child: const IntermediateWidget()
);
}
}

// Intermediate widget to show how inherited widgets
// can propagate changes down the widget tree
class IntermediateWidget extends StatelessWidget {
// Using a const constructor makes the widget cacheable
const IntermediateWidget();

@override
Widget build(BuildContext context) {
return new Center(
child: new Padding(
padding: new EdgeInsets.all(10.0),
child: const NameWidget()));
}
}

class NameWidget extends StatelessWidget {
const NameWidget();

@override
Widget build(BuildContext context) {
final inheritedWidget = NameInheritedWidget.of(context);
return new Text(
inheritedWidget.name,
style: Theme.of(context).textTheme.display1,
);
}
}

关于Flutter - 如何将用户数据传递给所有 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46990200/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com