我对InheritedWidget有疑问。由于我的应用程序中的大多数页面都使用了用户对象,因此我创建了一个名为UserProvider的InheritedWidget类,因此无需沿着小部件树传递用户对象。在我尝试注销并用另一个用户登录之前,它工作正常。用户仍然是旧的。我做了一些研究,似乎InheritedWidget类中的值无法更改。有一种方法可以重写它,这样我就可以利用InheritedWidget并仍然能够更改用户对象的值?
UserProvider类: UserProvider类扩展了InheritedWidget { UserProvider({Key key,Widget child,this.user}):超级(key:key,child:child); 最终用户;
/* @override
bool updateShouldNotify(InheritedWidget oldWidget) => true;
*/
@override
bool updateShouldNotify(UserProvider oldWidget) {
return user != oldWidget.user;
}
static UserProvider of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(UserProvider) as UserProvider);
}
}
首页类:
class HomePage extends StatefulWidget {
HomePage({this.auth, this.onSignedOut,this.userId});
final BaseAuth auth;
final VoidCallback onSignedOut;
final String userId;
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _userName;
String _userEmail;
String _userPicURL;
User currentUser;
void _signOut() async {
try {
await widget.auth.signOut();
widget.onSignedOut();
} catch (e) {
print(e);
}
}
@override
void initState() {
super.initState();
currentUser = User(widget.userId);
currentUser.loadUserData();
...
@override
Widget build(BuildContext context) {
return UserProvider(
user: currentUser,
...
LoginPage类:
class LoginPage extends StatefulWidget {
LoginPage({this.auth, this.onSignedIn});
final BaseAuth auth;
final VoidCallback onSignedIn;
@override
//_LoginPageState createState() => _LoginPageState();
State<StatefulWidget> createState() => _LoginPageState();
}
enum FormType {
login,
register
}
class _LoginPageState extends State<LoginPage> {
final formKey = new GlobalKey<FormState>();
String _uid;
String _email;
String _password;
String _birthday;
String _fullname;
FormType _formType = FormType.login;
bool validateAndSave() {
final form = formKey.currentState;
if (form.validate()) {
form.save();
return true;
} else {
return false;
}
}
void _addData(String email, String fullname, String birthday) async {
_uid = await widget.auth.currentUser();
Firestore.instance.runTransaction((Transaction transaction) async{
Firestore.instance.collection("Users").document(_uid).setData(
{
"id": _uid,
"email" : email,
"fullname": fullname,
"birthday" : birthday
});
});
}
void validateAndSubmit() async{
final form = formKey.currentState;
if (validateAndSave()) {
try {
if (_formType == FormType.login) {
String userId = await widget.auth.signInWithEmailAndPassword( _email.trim(), _password.trim());
} else {
String userId = await widget.auth.createUserWithEmailAndPassword( _email.trim(), _password.trim());
_addData(_email, _fullname, _birthday);
}
widget.onSignedIn();
}
catch (e)
{
print('Error: $e');
}
} else {
print('form is invalid');
}
}
void moveToRegister () {
formKey.currentState.reset();
setState(() {
_formType = FormType.register;
});
}
void moveToLogin () {
formKey.currentState.reset();
setState(() {
_formType = FormType.login;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Login"),
backgroundColor: const Color(0xFF86d2dd),
),
body: new Container(
padding: EdgeInsets.all(16.0),
child: new Form(
key: formKey,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: buildInputs() + buildSubmitButtons(),
)
)
)
);
}
List<Widget> buildInputs() {
if (_formType == FormType.login) {
return [
new TextFormField(
decoration: new InputDecoration(labelText: "Email"),
validator: (value) => value.isEmpty ? 'Email can\'t be empty' : null,
onSaved: (value) => _email = value,
),
new TextFormField(
decoration: new InputDecoration(labelText: "Password"),
obscureText: true,
validator: (value) => value.isEmpty ? 'Password can\'t be empty' : null,
onSaved: (value) => _password = value,
),
];
} else {
return [
new TextFormField(
decoration: new InputDecoration(labelText: "Email"),
validator: (value) => value.isEmpty ? 'Email can\'t be empty' : null,
onSaved: (value) => _email = value,
),
new TextFormField(
decoration: new InputDecoration(labelText: "Password"),
obscureText: true,
validator: (value) => value.isEmpty ? 'Password can\'t be empty' : null,
onSaved: (value) => _password = value,
),
new TextFormField(
decoration: new InputDecoration(labelText: "Name "),
validator: (value) => value.isEmpty ? 'Name can\'t be empty' : null,
onSaved: (value) => _fullname = value,
),
new TextFormField(
decoration: new InputDecoration(labelText: "Birthday (MM/DD)"),
validator: (value) => value.isEmpty ? 'Birthday can\'t be empty' : null,
onSaved: (value) => _birthday = value,
),
];
}
}
List<Widget> buildSubmitButtons() {
if (_formType == FormType.login) {
return [
new RaisedButton(
child: new Text('Login', style: new TextStyle(fontSize: 20.0)),
onPressed: validateAndSubmit,
),
new FlatButton(
child: new Text('Create an account', style: new TextStyle(fontSize: 20.0)),
onPressed: moveToRegister,
)
];
} else {
return [
new RaisedButton(
child: new Text('Create an account', style: new TextStyle(fontSize: 20.0)),
onPressed: validateAndSubmit,
),
new FlatButton(
child: new Text('Have an account? Login', style: new TextStyle(fontSize: 20.0)),
onPressed: moveToLogin,
)
];
}
}
}
答案 0 :(得分:0)
我自己正在尝试InheritedWidget。阅读https://stackoverflow.com/a/51912243/7050833之后,我将尝试将UserProvider放在MaterialApp上方。
[3, 5, "a", "b"]