Flutter 颤振-如何将用户数据传递到所有视图
我对Flitter世界和移动应用程序开发还不熟悉,正在努力解决如何在我的应用程序中传递用户数据的问题 我尝试过几种方法,但没有一种是很好的,我相信我应该遵循一些最佳实践模式 因为它使示例更容易,所以我使用firebase进行身份验证。 我目前有一个单独的登录路径。登录后,我希望在大多数视图中使用用户模型来检查要显示的内容的权限,在抽屉中显示用户信息,等等 Firebase有一个Flutter 颤振-如何将用户数据传递到所有视图,flutter,dart,firebase-authentication,pass-data,Flutter,Dart,Firebase Authentication,Pass Data,我对Flitter世界和移动应用程序开发还不熟悉,正在努力解决如何在我的应用程序中传递用户数据的问题 我尝试过几种方法,但没有一种是很好的,我相信我应该遵循一些最佳实践模式 因为它使示例更容易,所以我使用firebase进行身份验证。 我目前有一个单独的登录路径。登录后,我希望在大多数视图中使用用户模型来检查要显示的内容的权限,在抽屉中显示用户信息,等等 Firebase有一个等待firebaseAuth.currentUser()在您可能需要用户的任何地方调用它是否是最佳做法?如果是的话,打电
等待firebaseAuth.currentUser()代码>在您可能需要用户的任何地方调用它是否是最佳做法?如果是的话,打电话的最佳地点是哪里
显示了在允许写入之前对用户进行身份验证的一个很好的示例。但是,如果页面需要检查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);
}
继承的小部件
本文展示了一个使用InheritedWidget
的好模式。当我将继承的小部件放在MaterialApp级别时,当身份验证状态更改时,子部件不会更新(我肯定我做得不对)
如果您能提供关于最佳实践模式的任何建议,或提供参考资料的链接,我将不胜感激。我建议您进一步研究继承的小部件;下面的代码显示了如何将它们用于异步更新数据:
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,
);
}
}
导入'dart:convert';
进口“包装:颤振/材料.省道”;
将“package:http/http.dart”导入为http;
void main(){
runApp(新材料)PP(
标题:“继承的小部件演示”,
主题:新主题数据(
主样本:颜色。蓝色,
),
家:新脚手架(
appBar:新的appBar(
标题:新文本(“继承的小部件示例”),
),
正文:新名称页());
}
//用于管理名称的继承小部件
类名InheritedWidget扩展了InheritedWidget{
常量NameInheritedWidget({
关键点,
这个名字,
Widget child}):超级(key:key,child:child);
最后的字符串名;
@凌驾
bool updateShouldNotify(NameInheritedWidget old){
打印('In updateShouldNotify');
返回名称!=old.name;
}
的静态NameInheritedWidget(BuildContext上下文){
//您也可以直接在此处返回名称
//因为只有一个领域
返回context.inheritFromWidgetOfExactType(名称InheritedWidget);
}
}
//用于管理名称数据的有状态小部件
类NamePage扩展了StatefulWidget{
@凌驾
_NamePageState createState()=>new_NamePageState();
}
//用于管理通过HTTP获取名称数据的状态
类_NamePageState扩展状态{
字符串名称='占位符';
//通过HTTP异步获取名称
_get()异步{
var res=wait http.get('https://jsonplaceholder.typicode.com/users');
var name=json.decode(res.body)[0]['name'];
setState(()=>this.name=name);
}
@凌驾
void initState(){
super.initState();
_get();
}
@凌驾
小部件构建(构建上下文){
返回新名称InheritedWidget(
姓名:姓名,,
子项:const IntermediateWidget()
);
}
}
//中间小部件,用于显示如何继承小部件
//可以将更改传播到小部件树
类IntermediateWidget扩展了无状态小部件{
//使用const构造函数使小部件可缓存
常数IntermediateWidget();
@凌驾
小部件构建(构建上下文){
返回新中心(
孩子:新的填充物(
填充:新边缘设置。全部(10.0),
子:const NameWidget());
}
}
类名小部件扩展了无状态小部件{
const NameWidget();
@凌驾
小部件构建(构建上下文){
final inheritedWidget=NameInheritedWidget.of(上下文);
返回新文本(
inheritedWidget.name,
样式:Theme.of(context).textTheme.display1,
);
}
}
由于这个问题,我遇到了另一个问题
所以我提出的解决方案有点混乱,我创建了一个单独的实例dart页面,并将其导入到每个页面
GoogleSignInAccount Guser = googleSignIn.currentUser;
FirebaseUser Fuser;
我在登录时将用户存储在那里,并检查每个StateWidget是否为null
Future<Null> _ensureLoggedIn() async {
if (Guser == null) Guser = await googleSignIn.signInSilently();
if (Fuser == null) {
await googleSignIn.signIn();
analytics.logLogin();
}
if (await auth.currentUser() == null) {
GoogleSignInAuthentication credentials =
await googleSignIn.currentUser.authentication;
await auth.signInWithGoogle(
idToken: credentials.idToken,
accessToken: credentials.accessToken,
);
}
Future\u ensureLoggedIn()异步{
如果(Guser==null)Guser=wait googleSignIn.signizely();
if(Fuser==null){
等待谷歌签名;
logLogin();
}
if(等待auth.currentUser()==null){
谷歌签名认证证书=
等待googleSignIn.currentUser.authentication;
用谷歌等待auth.signin(
idToken:credentials.idToken,
accessToken:credentials.accessToken,
);
}
这是我的旧代码,我在当前的应用程序中清理了它,但我现在手头没有这些代码。只需签出空用户并重新登录即可
我对大多数Firebase实例也这么做,因为我的应用程序上有3个以上的页面,继承的小部件对我的懒惰的mathod来说太多了,
我只是创建了一个新文件,比如userdata.dart,然后在上面添加任何变量,比如dynamic Profile=null
内部userdata.dart
//only put this or anything u want.
dynamic Profile = null;
//import that file
import '../userdata.dart';
class startingpage extends ...{
...
//set data to store..
Profile = 'user profile';
...
}
//import that file
import '../userdata.dart';
class anotherpage extends...{
...
}
class .. State ...{
...
//set the data to variable
dynamic userdata = Profile;
print('this is my lazy pass data' + userdata.toString());
...
}
在开始页面。省道
//only put this or anything u want.
dynamic Profile = null;
//import that file
import '../userdata.dart';
class startingpage extends ...{
...
//set data to store..
Profile = 'user profile';
...
}
//import that file
import '../userdata.dart';
class anotherpage extends...{
...
}
class .. State ...{
...
//set the data to variable
dynamic userdata = Profile;
print('this is my lazy pass data' + userdata.toString());
...
}
要使用数据,只需在中声明和使用
另一页。省道
//only put this or anything u want.
dynamic Profile = null;
//import that file
import '../userdata.dart';
class startingpage extends ...{
...
//set data to store..
Profile = 'user profile';
...
}
//import that file
import '../userdata.dart';
class anotherpage extends...{
...
}
class .. State ...{
...
//set the data to variable
dynamic userdata = Profile;
print('this is my lazy pass data' + userdata.toString());
...
}
我更喜欢使用带有定位器的服务,使用
如果愿意,请使用缓存数据创建UserService:
class UserService {
final Firestore _db = Firestore.instance;
final String _collectionName = 'users';
CollectionReference _ref;
User _cachedUser; //<----- Cached Here
UserService() {
this._ref = _db.collection(_collectionName);
}
User getCachedUser() {
return _cachedUser;
}
Future<User> getUser(String id) async {
DocumentSnapshot doc = await _ref.document(id).get();
if (!doc.exists) {
log("UserService.getUser(): Empty companyID ($id)");
return null;
}
_cachedUser = User.fromDocument(doc.data, doc.documentID);
return _cachedUser;
}
}
并在main()中实例化
就这样!您可以通过以下方式调用您的服务+缓存数据:
.....
UserService _userService = locator<UserService>();
@override
void initState() {
super.initState();
_user = _userService.getCachedUser();
}
。。。。。
UserService _UserService=locator();
@凌驾
void initState(){
super.initState();
_user=_userService.getCachedUser();
}
您可以使用GetX软件包检查用户是否已登录,获取用户数据,并在整个应用程序中访问这些数据