在构建过程中更新值时使用Flutter Provider出现问题

时间:2020-03-23 19:31:13

标签: flutter

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

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

1 个答案:

答案 0 :(得分:2)

您必须记住,每次调用方法updateUserInfo时,都会触发notifyListeners(),它试图重建脏的窗口小部件。没有参数Provider.of<T>(context)的{​​{1}}也做同样的事情。因此,将调用2个重建触发器,从而导致错误。

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

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

例如;

listen: false

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

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


}

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