-
-
Save ericwindmill/f790bd2456e6489b1ab97eba246fd4c6 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart'; | |
import 'package:simple_inherit/state_container.dart'; | |
class UpdateUserScreen extends StatelessWidget { | |
static final GlobalKey<FormState> formKey = new GlobalKey<FormState>(); | |
static final GlobalKey<FormFieldState<String>> firstNameKey = | |
new GlobalKey<FormFieldState<String>>(); | |
static final GlobalKey<FormFieldState<String>> lastNameKey = | |
new GlobalKey<FormFieldState<String>>(); | |
static final GlobalKey<FormFieldState<String>> emailKey = | |
new GlobalKey<FormFieldState<String>>(); | |
final User user; | |
const UpdateUserScreen({Key key, this.user}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
final container = StateContainer.of(context); | |
return new Scaffold( | |
appBar: new AppBar( | |
title: new Text('Edit User Info'), | |
), | |
body: new Padding( | |
padding: new EdgeInsets.all(16.0), | |
child: new Form( | |
key: formKey, | |
autovalidate: false, | |
child: new ListView( | |
children: [ | |
new TextFormField( | |
key: firstNameKey, | |
style: Theme.of(context).textTheme.headline, | |
decoration: new InputDecoration( | |
hintText: 'First Name', | |
), | |
), | |
new TextFormField( | |
key: lastNameKey, | |
style: Theme.of(context).textTheme.headline, | |
decoration: new InputDecoration( | |
hintText: 'Last Name', | |
), | |
), | |
new TextFormField( | |
key: emailKey, | |
style: Theme.of(context).textTheme.headline, | |
decoration: new InputDecoration( | |
hintText: 'Email Address', | |
), | |
) | |
], | |
), | |
), | |
), | |
floatingActionButton: new FloatingActionButton( | |
child: new Icon(Icons.add), | |
onPressed: () { | |
final form = formKey.currentState; | |
if (form.validate()) { | |
var firstName = firstNameKey.currentState.value; | |
var lastName = lastNameKey.currentState.value; | |
var email = emailKey.currentState.value; | |
if (firstName == '') { | |
firstName = null; | |
} | |
if (lastName == '') { | |
lastName = null; | |
} | |
if (email == '') { | |
email = null; | |
} | |
container.updateUserInfo( | |
firstName: firstName, | |
lastName: lastName, | |
email: email, | |
); | |
Navigator.pop(context); | |
} | |
}, | |
), | |
); | |
} | |
} |
import 'package:flutter/material.dart'; | |
import 'package:simple_inherit/form_page.dart'; | |
import 'package:simple_inherit/state_container.dart'; | |
void main() { | |
runApp(new StateContainer(child: new TodoApp())); | |
} | |
class TodoApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return new MaterialApp( | |
title: 'Some Todos', | |
home: new HomeScreen(), | |
); | |
} | |
} | |
class HomeScreen extends StatefulWidget { | |
@override | |
HomeScreenState createState() => new HomeScreenState(); | |
} | |
class HomeScreenState extends State<HomeScreen> { | |
User user; | |
Widget get _userInfo { | |
return new Center( | |
child: new Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: <Widget>[ | |
new Text("${user.firstName} ${user.lastName}", | |
style: new TextStyle(fontSize: 24.0)), | |
new Text(user.email, style: new TextStyle(fontSize: 24.0)), | |
], | |
), | |
); | |
} | |
Widget get _logInPrompt { | |
return new Center( | |
child: new Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: <Widget>[ | |
new Text('Please add user information'), | |
], | |
), | |
); | |
} | |
void _updateUser(BuildContext context) { | |
Navigator.push( | |
context, | |
new MaterialPageRoute( | |
fullscreenDialog: true, | |
builder: (context) { | |
return new UpdateUserScreen(); | |
}, | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final container = StateContainer.of(context); | |
user = container.user; | |
var body = user != null ? _userInfo : _logInPrompt; | |
return new Scaffold( | |
appBar: new AppBar( | |
title: new Text('Inherited Widget Test'), | |
), | |
body: body, | |
floatingActionButton: new FloatingActionButton( | |
onPressed: () => _updateUser(context), | |
child: new Icon(Icons.edit), | |
), | |
); | |
} | |
} |
import 'package:flutter/cupertino.dart'; | |
import 'package:flutter/foundation.dart'; | |
class User { | |
String firstName; | |
String lastName; | |
String email; | |
User(this.firstName, this.lastName, this.email); | |
} | |
class StateContainer extends StatefulWidget { | |
final Widget child; | |
final User user; | |
StateContainer({ | |
@required this.child, | |
this.user, | |
}); | |
static StateContainerState of(BuildContext context) { | |
return (context.inheritFromWidgetOfExactType(_InheritedStateContainer) | |
as _InheritedStateContainer) | |
.data; | |
} | |
@override | |
StateContainerState createState() => new StateContainerState(); | |
} | |
class StateContainerState extends State<StateContainer> { | |
User user; | |
void updateUserInfo({firstName, lastName, email}) { | |
if (user == null) { | |
user = new User(firstName, lastName, email); | |
setState(() { | |
user = user; | |
}); | |
} else { | |
setState(() { | |
user.firstName = firstName ?? user.firstName; | |
user.lastName = lastName ?? user.lastName; | |
user.email = email ?? user.email; | |
}); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return new _InheritedStateContainer( | |
data: this, | |
child: widget.child, | |
); | |
} | |
} | |
class _InheritedStateContainer extends InheritedWidget { | |
final StateContainerState data; | |
_InheritedStateContainer({ | |
Key key, | |
@required this.data, | |
@required Widget child, | |
}) : super(key: key, child: child); | |
@override | |
bool updateShouldNotify(_InheritedStateContainer old) => true; | |
} |
Thank you for this example. :-)
Keeping a state in flutter is not that easy ... :P
I'm lucky the state of my hard drive is not that "volatile"
Thank you. Very good example and I feel very comfortable with just enough complexity. But for starters or absolute beginners, a diagram that map out the design for this particular app would be very helpful.
Thank you for this example.:)
i have a problem:
https://gist.github.com/ericwindmill/f790bd2456e6489b1ab97eba246fd4c6#file-form_page-dart-L75
How does this function become optional?
Please rename to "Flutter Complex inherited Widget Example"
Cool! it works for me! thanks
I found an issue. If you're on the 2nd page of a PageView and you press a button that runs container.updateUserInfo(), the PageView returns to its first page. I'm guessing this is because the PageView rebuilds and loses its state. How would you prevent PageView from returning to its first page in this case?
Anyone have an idea why, this code directly returned true from updateShouldNotify method, without comparing data object?
Nowadays you might use:
return (context.dependOnInheritedWidgetOfExactType<_InheritedStateContainer>()
).data;
instead of:
return (context.inheritFromWidgetOfExactType(_InheritedStateContainer)
as _InheritedStateContainer)
.data;
given inheritFromWidgetOfExactType is deprecated
"StateContainerState"
This example is very cool. I understood the logic behind state management mechanisms.
Got anything simpler?