initState() is called twice on the first Widget I route to.
I have removed all method calls and work being done in the initState() method to exclude any possibility that it somehow calls itself. All it does is calling super.initState().
routes.dart:
final routes = {
'/login' : (BuildContext context) => new LoginPage(),
'/' : (BuildContext context) => new LoginPage()
};
main.dart:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Personnel Ledger',
initialRoute: '/login',
routes: routes,
theme: ThemeData(
scaffoldBackgroundColor: Color(0xFF30778B)
),
);
}
}
LoginPage.dart:
class LoginPage extends StatefulWidget {
@override
LoginPageState createState() => LoginPageState();
}
class LoginPageState extends State<LoginPage> {
TextEditingController emailTextfieldCtrl;
TextEditingController passwordTextfieldCtrl;
AuthHttpService authHttpService;
bool loggaInDisabled;
Widget invalidCredentialsText;
@override
void initState() {
super.initState();
// setInvalidCredentialsTextVisibleWithoutSetState(false);
// authHttpService = new AuthHttpService();
// emailTextfieldCtrl = new TextEditingController();
// passwordTextfieldCtrl = new TextEditingController();
loggaInDisabled = true;
// refreshApplicationAccessToken();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: SafeArea(
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF30778B), Color(0xFF2F3648)])),
child: Center(
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Spacer(
flex: 11,
),
Flexible(
flex: 50,
child: Container(
child: Image.asset("assets/knowe-logo.png"),
),
),
],
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Spacer(
flex: 35,
),
Flexible(
flex: 10,
child: Container(
child: Row(
children: <Widget>[
Spacer(
flex: 1,
),
Flexible(
flex: 7,
child: Theme(
data:
ThemeData(hintColor: Color(0xFF9E9C9C)),
child: TextField(
style:
TextStyle(color: Color(0xFF9E9C9C)),
cursorColor: Color(0xFF9E9C9C),
controller: emailTextfieldCtrl,
onChanged: emailTextfieldChanged,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.person,
size: 30,
color: Color(0xFF9E9C9C),
),
labelText: "Email",
border: new UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xFF9E9C9C),
style: BorderStyle.solid,
width: 2))),
),
),
),
Spacer(
flex: 1,
)
],
),
),
),
Flexible(
flex: 10,
child: Container(
margin: EdgeInsets.only(top: 5),
child: Row(
children: <Widget>[
Spacer(
flex: 1,
),
Flexible(
flex: 7,
child: Theme(
data:
ThemeData(hintColor: Color(0xFF9E9C9C)),
child: TextField(
obscureText: true,
style:
TextStyle(color: Color(0xFF9E9C9C)),
cursorColor: Color(0xFF9E9C9C),
controller: passwordTextfieldCtrl,
onChanged: passwordTextfieldChanged,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.lock,
size: 26,
color: Color(0xFF9E9C9C),
),
labelText: "Lösenord",
border: new UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xFF9E9C9C),
style: BorderStyle.solid,
width: 2))),
),
),
),
Spacer(flex: 1)
],
),
),
),
Flexible(
flex: 10,
child: Container(
child: invalidCredentialsText,
)),
Flexible(
flex: 20,
child: Container(
margin: EdgeInsets.only(top: 0),
child: Row(
children: <Widget>[
Spacer(
flex: 1,
),
Expanded(
flex: 7,
child: Container(
height: 50,
child: RaisedButton(
disabledColor: Color(0xff395A52),
child: Text(
"Logga in",
style: TextStyle(
color: loggaInDisabled
? Color(0xff7a7a7a)
: Colors.white),
),
onPressed: loggaInDisabled
? null
: loggaInPressed,
color: Color(0xff10846D),
),
),
),
Spacer(flex: 1)
],
),
),
),
Container(
margin: EdgeInsets.only(top: 7.5),
child: InkWell(
child: Text(
"Glömt lösenord?",
style: TextStyle(color: Color(0xFF9E9C9C)),
),
onTap: glomtLosenordPressed,
),
),
Spacer(
flex: 10,
),
],
)
],
),
),
),
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment.bottomLeft,
padding: EdgeInsets.only(left: 15, bottom: 10),
color: Colors.transparent,
child: InkWell(
onTap: privacyPolicyTapped,
child: Text("Privacy policy",
style: TextStyle(
color: Color(0xFF9E9C9C),
fontSize: 15,
decoration: TextDecoration.underline)),
),
)
],
),
)
],
)
],
),
),
);
}
setInvalidCredentialsTextVisible(bool show) {
setState(() {
if (show)
invalidCredentialsText = Row(
children: <Widget>[
Spacer(flex: 1),
Flexible(
flex: 7,
child: Column(
children: <Widget>[
Flexible(
flex: 4,
child: Container(
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
Flexible(
flex: 1,
child: Icon(
Icons.error,
size: 20,
color: Color(0xFF9E9C9C),
),
),
Flexible(
flex: 5,
child: Container(
padding: EdgeInsets.only(left: 2.5),
child: Text(
"Invalid email or password",
style: TextStyle(color: Color(0xFF9E9C9C)),
),
),
)
],
),
),
),
Spacer(
flex: 2,
)
],
),
),
Spacer(flex: 1)
],
);
else
invalidCredentialsText = Row(
children: <Widget>[
Spacer(flex: 1),
Flexible(
flex: 7,
child: Column(
children: <Widget>[
Flexible(
flex: 3,
child: Container(
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
Flexible(
flex: 1,
child: Icon(
Icons.error,
size: 20,
color: Color(0x009E9C9C),
),
),
Flexible(
flex: 5,
child: Container(
padding: EdgeInsets.only(left: 2.5),
child: Text(
"",
style: TextStyle(color: Color(0xFF9E9C9C)),
),
),
)
],
),
),
),
Spacer(
flex: 2,
)
],
),
),
Spacer(flex: 1)
],
);
});
}
setInvalidCredentialsTextVisibleWithoutSetState(bool show) {
if (show)
invalidCredentialsText = Row(
children: <Widget>[
Spacer(flex: 1),
Flexible(
flex: 7,
child: Column(
children: <Widget>[
Flexible(
flex: 4,
child: Container(
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
Flexible(
flex: 1,
child: Icon(
Icons.error,
size: 20,
color: Color(0xFF9E9C9C),
),
),
Flexible(
flex: 5,
child: Container(
padding: EdgeInsets.only(left: 2.5),
child: Text(
"Invalid email or password",
style: TextStyle(color: Color(0xFF9E9C9C)),
),
),
)
],
),
),
),
Spacer(
flex: 2,
)
],
),
),
Spacer(flex: 1)
],
);
else
invalidCredentialsText = Row(
children: <Widget>[
Spacer(flex: 1),
Flexible(
flex: 7,
child: Column(
children: <Widget>[
Flexible(
flex: 3,
child: Container(
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
Flexible(
flex: 1,
child: Icon(
Icons.error,
size: 20,
color: Color(0x009E9C9C),
),
),
Flexible(
flex: 5,
child: Container(
padding: EdgeInsets.only(left: 2.5),
child: Text(
"",
style: TextStyle(color: Color(0xFF9E9C9C)),
),
),
)
],
),
),
),
Spacer(
flex: 2,
)
],
),
),
Spacer(flex: 1)
],
);
}
privacyPolicyTapped() {
launch("https://www.knowe.se/policy.html");
}
emailTextfieldChanged(String newEmail) {
setState(() {
loggaInDisabled = shouldDisableLoggaIn();
});
}
passwordTextfieldChanged(String newPassword) {
setState(() {
loggaInDisabled = shouldDisableLoggaIn();
});
}
bool shouldDisableLoggaIn() {
var email = emailTextfieldCtrl.text;
var password = passwordTextfieldCtrl.text;
return !(email != null &&
email != "" &&
password != null &&
password != "");
}
loggaInPressed() {
logIn();
}
logIn() {
var email = emailTextfieldCtrl.text;
var password = passwordTextfieldCtrl.text;
var appId = "4d45d54d45d45dd45d45d54d54d54d54";
var response = authHttpService.logIn(email, password, appId);
onLoading();
response
.then((response) async {
Navigator.pop(context);
if (response.statusCode == 200) {
setInvalidCredentialsTextVisible(false);
var tokensModel = TokensModel.fromJson(json.decode(response.body));
final prefs = await SharedPreferences.getInstance();
prefs.setString("RefreshToken", tokensModel.refreshToken);
prefs.setString(
"ApplicationAccessToken", tokensModel.appAccessToken);
navigateToMainMenuPage();
} else
setInvalidCredentialsTextVisible(true);
})
.timeout(Duration(seconds: 10))
.catchError((error) {
Navigator.pop(context);
showMessageDialog(
"Fel vid inloggning", "Kunde inte få kontakt med servern.");
});
}
configureFCM() {
// var fcmHelper = new FCMHelper();
// fcmHelper.configureFCM(context);
// fcmHelper.registerFCMToken(userModel);
}
glomtLosenordPressed() {
navigateToResetPasswordPage();
}
refreshApplicationAccessToken() async {
var prefs = await SharedPreferences.getInstance();
var refreshToken = prefs.getString("RefreshToken");
if (refreshToken != null && refreshToken != "") {
var response =
authHttpService.refreshApplicationAccessToken(refreshToken);
onLoading();
response
.then((response) async {
Navigator.pop(context);
if (response.statusCode == 200) {
var tokensModel =
TokensModel.fromJson(json.decode(response.body));
var applicationAccessToken = tokensModel.appAccessToken;
var prefs = await SharedPreferences.getInstance();
prefs.setString("ApplicationAccessToken", applicationAccessToken);
navigateToMainMenuPage();
} else
showMessageDialog("Inloggningssessionen utgången",
"Logga in igen med dina uppgifter.");
})
.timeout(Duration(seconds: 10))
.catchError((error) {
Navigator.pop(context);
showMessageDialog(
"Fel vid inloggning", "Kunde inte få kontakt med servern.");
});
}
}
navigateToMainMenuPage() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MainMenuPage()),
);
}
navigateToResetPasswordPage() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ResetPasswordPage()),
);
}
void onLoading() {
showDialog(
context: context,
barrierDismissible: false,
builder: (_) => Scaffold(
backgroundColor: Color.fromRGBO(0, 0, 0, 0.25),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 40,
height: 40,
child: CircularProgressIndicator(strokeWidth: 5)),
Container(
margin: EdgeInsets.only(top: 15),
child: Text(
"Loggar in...",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
],
),
)),
);
}
void showMessageDialog(String title, String body) {
try {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(title),
content: new Text(body),
);
});
} catch (e) {
print(e.toString());
}
}
}
Actual result: initState() method in LoginPage is called twice.
Expected result and goal: initState() should only be called once.
This is a combination of two facts: each route is entirely independent. / do not share state with /login , therefore going from / to /login will trigger an initState on the LoginPage from /login . initialRoute: '/login' does not mean that the app starts directly on /login .
3. initState() This is the first method called when the widget is created (after the class constructor, of course.) initState is called once and only once.
The initState() is a method that is called when an object for your stateful widget is created and inserted inside the widget tree. It is basically the entry point for the Stateful Widgets.
Basically the answer is yes: you should call setstate() all the time you are to execute an asynchronous function inside initstate() .
This is a combination of two facts:
/
do not share state with /login
, therefore going from /
to /login
will trigger an initState
on the LoginPage
from /login
.initialRoute: '/login'
does not mean that the app starts directly on /login
.With the initialRoute
argument to /foo/bar
, the app will start with the following route history:
/
/foo
/foo/bar
As such, even though you have an initialRoute
property, /
is still pushed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With