flutter - 为什么 initState() 被调用了两次?

标签 flutter

initState() 在我路由到的第一个 Widget 上被调用了两次。

我已经删除了 initState() 方法中的所有方法调用和正在完成的工作,以排除它以某种方式调用自身的任何可能性。它所做的只是调用 super.initState()。

routes.dart:

final routes = {
  '/login' : (BuildContext context) => new LoginPage(),
  '/' : (BuildContext context) => new LoginPage()
};

主飞镖:

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)
      ),
    );
  }
}

登录页面.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());
    }
  }
}

实际结果: LoginPage 中的 initState() 方法被调用了两次。

预期结果和目标: initState() 应该只被调用一次。

最佳答案

这是两个事实的结合:

  • 每条路线都是完全独立的。 / 不与 /login 共享状态,因此从 //login 将触发 /loginLoginPage 上的 initState
  • initialRoute: '/login' 并不意味着应用在 /login直接启动。

通过 /foo/barinitialRoute 参数,应用程序将从以下路线历史开始:

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

因此,即使您有一个 initialRoute 属性,/ 仍然会被推送。

关于flutter - 为什么 initState() 被调用了两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56145378/

相关文章:

flutter - 卡住构造函数初始值设定项

flutter - 根据 TextField 状态更改 TextField 背景颜色

安卓工作室 : Open Android Module in Android Studio option is missing in flutter project

Flutter/Dart 逻辑,用于将 API Future 的返回值分配给另一个变量/函数

flutter - Flutter 中哪个widget 可以作为新路由的root widget(支持Text)而不覆盖整个屏幕?

flutter - 如何让 Flutter 应用根据不同的屏幕尺寸做出响应?

Flutter Web Dashboard Content - 最佳实践?

Flutter如何使用setState()

android - 缓慢 flutter 的 GridView

flutter - 在charts_flutter中设置轴的最小和最大范围