Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振-如何将用户数据传递到所有视图_Flutter_Dart_Firebase Authentication_Pass Data - Fatal编程技术网

Flutter 颤振-如何将用户数据传递到所有视图

Flutter 颤振-如何将用户数据传递到所有视图,flutter,dart,firebase-authentication,pass-data,Flutter,Dart,Firebase Authentication,Pass Data,我对Flitter世界和移动应用程序开发还不熟悉,正在努力解决如何在我的应用程序中传递用户数据的问题 我尝试过几种方法,但没有一种是很好的,我相信我应该遵循一些最佳实践模式 因为它使示例更容易,所以我使用firebase进行身份验证。 我目前有一个单独的登录路径。登录后,我希望在大多数视图中使用用户模型来检查要显示的内容的权限,在抽屉中显示用户信息,等等 Firebase有一个等待firebaseAuth.currentUser()在您可能需要用户的任何地方调用它是否是最佳做法?如果是的话,打电

我对Flitter世界和移动应用程序开发还不熟悉,正在努力解决如何在我的应用程序中传递用户数据的问题

我尝试过几种方法,但没有一种是很好的,我相信我应该遵循一些最佳实践模式

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

Firebase有一个
等待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软件包检查用户是否已登录,获取用户数据,并在整个应用程序中访问这些数据