Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is initState() called twice?

Tags:

flutter

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.

like image 283
Tobias Eliasson Avatar asked May 15 '19 09:05

Tobias Eliasson


People also ask

Why is initState called twice?

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 .

How many times is initState called?

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.

What is initState?

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.

Is initState called on Setstate?

Basically the answer is yes: you should call setstate() all the time you are to execute an asynchronous function inside initstate() .


1 Answers

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.

With the initialRoute argument to /foo/bar, the app will start with the following route history:

  1. /
  2. /foo
  3. /foo/bar

As such, even though you have an initialRoute property, / is still pushed.

like image 102
Rémi Rousselet Avatar answered Sep 28 '22 07:09

Rémi Rousselet