在构建过程中更新值时使用Flutter Provider出现问题 [英] Problem using Flutter Provider when updating a value during build

查看:116
本文介绍了在构建过程中更新值时使用Flutter Provider出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在检查用户是否已登录后,我正尝试在提供程序中更新我的uid.当我这样做时,即使应用程序不会崩溃,在构建窗口小部件时也会引发错误.这是代码:

I'm trying to update my uid in a provider just after checking whether a user is logged. When I do that, throws an error when building widgets even though the app does not crash. Here is the code:

class HandleAuth extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var user = Provider.of<FirebaseUser>(context);
    if (user != null) {
      print('user.uid is ${user.uid}');
      final loggedUserInfo = Provider.of<LoggedUserInfo>(context, listen: false);
      loggedUserInfo.updateUserInfo(user.uid);
      print('first scan screen user: ${loggedUserInfo.userUid}');

    }
    return (user == null)
            ? WelcomeNewUserScreen()
            : ServicesAroundMe();
  }
}

这是提供者:

class LoggedUserInfo with ChangeNotifier {
  String _uid;

  String get userUid {
    return _uid;
  }

  void updateUserInfo(String updatedUid) {
    _uid = updatedUid;
    print('updated uid is $_uid');
    notifyListeners();
  }

}

它抛出此错误:

不能将此ListenableProvider小部件标记为需要构建,因为该框架已经在构建小部件.仅当其某个祖先当前正在构建窗口小部件时,才可以将其标记为需要在构建阶段中构建.允许使用此异常是因为该框架先于子级构建父级窗口小部件,这意味着将始终构建一个肮脏的后代.否则,框架在此构建阶段可能不会访问此窗口小部件.调用setState()或markNeedsBuild()的小部件为:ListenableProvider

This ListenableProvider widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase. The widget on which setState() or markNeedsBuild() was called was: ListenableProvider

推荐答案

您必须记住,每次调用方法updateUserInfo时,都会触发notifyListeners(),它试图重建脏的窗口小部件.不带参数 listen:false Provider.of< T>(上下文)也具有相同的作用.因此,将调用2个重建触发器,从而导致错误.

You have to bear in mind that each time you call the method updateUserInfo, the notifyListeners() is triggered which tries to rebuild dirty widgets. Provider.of<T>(context) without the argument listen: false also does the same thing. Hence 2 rebuild trigger are called which cause the error.

与提供者合作时,建议使用流.

When working with a provider, it is advisable to use a stream.

要使代码更具可伸缩性,请为用户创建一个自定义类,然后使用ChangeNotifier或提供程序和流.

To make your code more scalable, create a custom class for your user and Either use ChangeNotifier or provider and streams.

例如;

class User {
  final String uid;
  final String displayName;
  User({ @required this.uid, this.displayName });
}

class Auth {

   User _firebaseUserMapper( FirebaseUser user) {
       if(user == null){
           return null;
       }
       return User(uid: user.uid, displayName: user.displayName);
   }

   Stream<User> get onAuthStateChange {
       return Firebase.instance.onAuthStateChanged.map(_firebaseUserMapper);
   }


}

在页面屏幕中,您会像下面这样

In your page screen, you use like bellow

class HandleAuth extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<Auth>(context, listen: false);
    return StreamBuilder<User>(
         stream: auth.onAuthStateChanged,
         builder: (BuildContext context, AsyncSnapshot snapshot) {
             if( snapshot.connectionState == ConnectionState.active) {
                   User user = snapshot.data;
                   if (user == null ){
                       return WelcomeNewUserScreen();
                   }
                   return Provider<User>.value(
                        value: user,
                        child: ServicesAroundMe(),
                   );
              }
              return Scaffold(
                  body: Center(
                      child: CircularProgressIndicator();
                  ),
              );
         }
    );
}

该流将永远侦听currentUser/newUser并导航到适当的页面.

The stream will forever listen for a currentUser/newUser and navigate to the appropriate page.

这篇关于在构建过程中更新值时使用Flutter Provider出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆