@@ -13,43 +13,46 @@ class MyApp extends StatelessWidget {
13
13
primarySwatch: Colors .blue,
14
14
),
15
15
home: LoginPage (
16
- inputLoginData : LoginData ( ),
16
+ onSignIn : () => print ( 'login successful!' ),
17
17
),
18
18
);
19
19
}
20
20
}
21
21
22
22
class LoginPage extends StatefulWidget {
23
- final LoginData inputLoginData;
24
- LoginPage ({@required this .inputLoginData});
23
+ final VoidCallback _onSignIn;
24
+
25
+ LoginPage ({@required onSignIn})
26
+ : assert (onSignIn != null ),
27
+ _onSignIn = onSignIn;
28
+
25
29
@override
26
- _LoginPageState createState () =>
27
- _LoginPageState (inputLoginData: inputLoginData);
30
+ _LoginPageState createState () => _LoginPageState ();
28
31
}
29
32
30
33
class _LoginPageState extends State <LoginPage > {
31
- final LoginData inputLoginData;
32
- _LoginPageState ({this .inputLoginData});
33
-
34
+ // maintains validators and state of form fields
34
35
final GlobalKey <FormState > _loginFormKey = GlobalKey <FormState >();
36
+
35
37
// manage state of modal progress HUD widget
36
- bool _inAsyncCall = false ;
38
+ bool _isInAsyncCall = false ;
37
39
38
- final LoginData _serverLoginData = LoginData (
39
- userName : 'username1' ,
40
- password : 'password1' ,
41
- ) ;
42
- bool _isValidUserName = true ; // managed by response from server
43
- bool _isValidPassword = true ; // managed by response from server
40
+ bool _isInvalidAsyncUser = false ; // managed after response from server
41
+ bool _isInvalidAsyncPass = false ; // managed after response from server
42
+
43
+ String _username ;
44
+ String _password;
45
+ bool _isLoggedIn = false ;
44
46
45
47
// validate user name
46
48
String _validateUserName (String userName) {
47
49
if (userName.length < 8 ) {
48
50
return 'Username must be at least 8 characters' ;
49
51
}
50
52
51
- if (! _isValidUserName) {
52
- _isValidUserName = true ;
53
+ if (_isInvalidAsyncUser) {
54
+ // disable message until after next async call
55
+ _isInvalidAsyncUser = false ;
53
56
return 'Incorrect user name' ;
54
57
}
55
58
@@ -62,8 +65,9 @@ class _LoginPageState extends State<LoginPage> {
62
65
return 'Password must be at least 8 characters' ;
63
66
}
64
67
65
- if (! _isValidPassword) {
66
- _isValidPassword = true ;
68
+ if (_isInvalidAsyncPass) {
69
+ // disable message until after next async call
70
+ _isInvalidAsyncPass = false ;
67
71
return 'Incorrect password' ;
68
72
}
69
73
@@ -74,35 +78,40 @@ class _LoginPageState extends State<LoginPage> {
74
78
if (_loginFormKey.currentState.validate ()) {
75
79
_loginFormKey.currentState.save ();
76
80
77
- // dismiss keyboard
81
+ // dismiss keyboard during async call
78
82
FocusScope .of (context).requestFocus (new FocusNode ());
79
83
80
84
// start the modal progress HUD
81
85
setState (() {
82
- _inAsyncCall = true ;
86
+ _isInAsyncCall = true ;
83
87
});
84
88
85
89
// Simulate a service call
86
90
Future .delayed (Duration (seconds: 1 ), () {
91
+ final _accountUsername = 'username1' ;
92
+ final _accountPassword = 'password1' ;
87
93
setState (() {
88
- if (inputLoginData.userName == _serverLoginData.userName) {
89
- _isValidUserName = true ;
90
- // only validate password if username exists in database
91
- if (inputLoginData.password == _serverLoginData.password)
92
- _isValidPassword = true ;
93
- else
94
- _isValidPassword = false ;
94
+ if (_username == _accountUsername) {
95
+ _isInvalidAsyncUser = false ;
96
+ if (_password == _accountPassword) {
97
+ // username and password are correct
98
+ _isInvalidAsyncPass = false ;
99
+ _isLoggedIn = true ;
100
+ } else
101
+ // username is correct, but password is incorrect
102
+ _isInvalidAsyncPass = true ;
95
103
} else {
96
- _isValidUserName = false ;
97
- // no such user, so password validator not triggered
98
- _isValidPassword = true ;
99
- }
100
- if (_isValidUserName && _isValidPassword) {
101
- inputLoginData.isLoggedIn = true ;
104
+ // incorrect username and have not checked password result
105
+ _isInvalidAsyncUser = true ;
106
+ // no such user, so no need to trigger async password validator
107
+ _isInvalidAsyncPass = false ;
102
108
}
103
109
// stop the modal progress HUD
104
- _inAsyncCall = false ;
110
+ _isInAsyncCall = false ;
105
111
});
112
+ if (_isLoggedIn)
113
+ // do something
114
+ widget._onSignIn ();
106
115
});
107
116
}
108
117
}
@@ -114,14 +123,16 @@ class _LoginPageState extends State<LoginPage> {
114
123
title: Text ('Modal Progress HUD Demo' ),
115
124
backgroundColor: Colors .blue,
116
125
),
126
+ // display modal progress HUD (heads-up display, or indicator)
127
+ // when in async call
117
128
body: ModalProgressHUD (
118
129
child: SingleChildScrollView (
119
130
child: Container (
120
131
padding: const EdgeInsets .all (16.0 ),
121
132
child: buildLoginForm (context),
122
133
),
123
134
),
124
- inAsyncCall: _inAsyncCall ,
135
+ inAsyncCall: _isInAsyncCall ,
125
136
// demo of some additional parameters
126
137
opacity: 0.5 ,
127
138
progressIndicator: CircularProgressIndicator (),
@@ -130,9 +141,8 @@ class _LoginPageState extends State<LoginPage> {
130
141
}
131
142
132
143
Widget buildLoginForm (BuildContext context) {
133
- final ThemeData themeData = Theme .of (context);
134
- final TextTheme textTheme = themeData.textTheme;
135
- // run the validators on reload
144
+ final TextTheme textTheme = Theme .of (context).textTheme;
145
+ // run the validators on reload to process async results
136
146
_loginFormKey.currentState? .validate ();
137
147
return Form (
138
148
key: this ._loginFormKey,
@@ -146,9 +156,7 @@ class _LoginPageState extends State<LoginPage> {
146
156
hintText: 'enter username' , labelText: 'User Name' ),
147
157
style: TextStyle (fontSize: 20.0 , color: textTheme.button.color),
148
158
validator: _validateUserName,
149
- onSaved: (String value) {
150
- inputLoginData.userName = value;
151
- },
159
+ onSaved: (value) => _username = value,
152
160
),
153
161
),
154
162
Padding (
@@ -160,22 +168,19 @@ class _LoginPageState extends State<LoginPage> {
160
168
hintText: 'enter password' , labelText: 'Password' ),
161
169
style: TextStyle (fontSize: 20.0 , color: textTheme.button.color),
162
170
validator: _validatePassword,
163
- onSaved: (String value) {
164
- inputLoginData.password = value;
165
- },
171
+ onSaved: (value) => _password = value,
166
172
),
167
173
),
168
174
Padding (
169
175
padding: const EdgeInsets .all (32.0 ),
170
176
child: RaisedButton (
171
- key: Key ('login' ),
172
177
onPressed: _submit,
173
178
child: Text ('Login' ),
174
179
),
175
180
),
176
181
Padding (
177
182
padding: const EdgeInsets .all (8.0 ),
178
- child: inputLoginData.isLoggedIn
183
+ child: _isLoggedIn
179
184
? Text (
180
185
'Login successful!' ,
181
186
key: Key ('loggedIn' ),
@@ -192,10 +197,3 @@ class _LoginPageState extends State<LoginPage> {
192
197
);
193
198
}
194
199
}
195
-
196
- class LoginData {
197
- String userName;
198
- String password;
199
- bool isLoggedIn;
200
- LoginData ({this .userName, this .password, this .isLoggedIn = false });
201
- }
0 commit comments