在检查用户是否已登录后,我正尝试在提供程序中更新我的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
答案 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并导航到适当的页面。