仅当 Flutter 中没有异常时才显示加载指示器

发布于 2025-01-09 07:15:00 字数 3528 浏览 1 评论 0原文

我创建了一个登录屏幕,一旦电子邮件和密码得到验证,用户将被推送到仪表板。所以我需要做的是,仅当没有抛出异常时才显示加载指示器,否则它应该显示我在 try-catch 中实现的警报。

登录按钮 -

SizedBox(
                    width: MediaQuery.of(context).size.width,
                    child: TextButton(
                      onPressed: signIn,
                      style: ButtonStyle(
                        padding: MaterialStateProperty.all<EdgeInsets>(
                          const EdgeInsets.fromLTRB(0, 20, 0, 20),
                        ),
                        shape:
                            MaterialStateProperty.all<RoundedRectangleBorder>(
                                RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(30.0))),
                        backgroundColor:
                            MaterialStateProperty.all(primaryColor),
                      ),
                      child: const Text(
                        'Login',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 15,
                          fontFamily: 'InterBold',
                        ),
                      ),
                    ),
                  ),

验证类 -

Future signIn() async {
    if (_key.currentState!.validate()) {
      try {
        await FirebaseAuth.instance.signInWithEmailAndPassword(
            email: emailController.text.trim(),
            password: passwordCrontroller.text.trim());

        errorMessage = '';
      } on FirebaseAuthException catch (e) {
        showDialog(
            context: context,
            builder: (context) => AlertDialog(
                  title: const Text(
                    'Error',
                    style: TextStyle(color: mainText),
                  ),
                  content: Text(
                    e.message!,
                    style: const TextStyle(color: secondaryText),
                  ),
                  contentPadding:
                      const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
                  backgroundColor: Colors.white,
                  actions: [
                    TextButton(
                        onPressed: () {
                          navigatorKey.currentState!.pop();
                        },
                        child: const Text(
                          'Close',
                          style: TextStyle(color: primaryColor),
                        ))
                  ],
                ));
      }
    }
  }

  String? validateEmail(String? formEmail) {
    String pattern = r'\w+@\w+\.\w+';
    RegExp regex = RegExp(pattern);

    if (formEmail == null || formEmail.isEmpty || !regex.hasMatch(formEmail)) {
      return '';
    }

    return null;
  }

  String? validatePassword(String? formPassword) {
    String pattern =
        r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{6,}$';
    RegExp regex = RegExp(pattern);
    if (formPassword == null ||
        formPassword.isEmpty ||
        !regex.hasMatch(formPassword)) {
      return '';
    }
    return null;
  }
}

加载指示器 -

showLoadingIndicatorDialog(BuildContext context) {
  return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) => const Center(
            child: CircularProgressIndicator(
              color: primaryColor,
            ),
          ));
}

I've created a login screen and once the email and password got verified user will be pushed to the dashboard. So what I need to do is, show a loading indicator only if there are no exceptions that get thrown otherwise it should show the alert which I've implemented with in a try-catch.

log-in button -

SizedBox(
                    width: MediaQuery.of(context).size.width,
                    child: TextButton(
                      onPressed: signIn,
                      style: ButtonStyle(
                        padding: MaterialStateProperty.all<EdgeInsets>(
                          const EdgeInsets.fromLTRB(0, 20, 0, 20),
                        ),
                        shape:
                            MaterialStateProperty.all<RoundedRectangleBorder>(
                                RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(30.0))),
                        backgroundColor:
                            MaterialStateProperty.all(primaryColor),
                      ),
                      child: const Text(
                        'Login',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 15,
                          fontFamily: 'InterBold',
                        ),
                      ),
                    ),
                  ),

Validation class -

Future signIn() async {
    if (_key.currentState!.validate()) {
      try {
        await FirebaseAuth.instance.signInWithEmailAndPassword(
            email: emailController.text.trim(),
            password: passwordCrontroller.text.trim());

        errorMessage = '';
      } on FirebaseAuthException catch (e) {
        showDialog(
            context: context,
            builder: (context) => AlertDialog(
                  title: const Text(
                    'Error',
                    style: TextStyle(color: mainText),
                  ),
                  content: Text(
                    e.message!,
                    style: const TextStyle(color: secondaryText),
                  ),
                  contentPadding:
                      const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
                  backgroundColor: Colors.white,
                  actions: [
                    TextButton(
                        onPressed: () {
                          navigatorKey.currentState!.pop();
                        },
                        child: const Text(
                          'Close',
                          style: TextStyle(color: primaryColor),
                        ))
                  ],
                ));
      }
    }
  }

  String? validateEmail(String? formEmail) {
    String pattern = r'\w+@\w+\.\w+';
    RegExp regex = RegExp(pattern);

    if (formEmail == null || formEmail.isEmpty || !regex.hasMatch(formEmail)) {
      return '';
    }

    return null;
  }

  String? validatePassword(String? formPassword) {
    String pattern =
        r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\
amp;*~]).{6,}

Loading indicator -

showLoadingIndicatorDialog(BuildContext context) {
  return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) => const Center(
            child: CircularProgressIndicator(
              color: primaryColor,
            ),
          ));
}
; RegExp regex = RegExp(pattern); if (formPassword == null || formPassword.isEmpty || !regex.hasMatch(formPassword)) { return ''; } return null; } }

Loading indicator -

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

第七度阳光i 2025-01-16 07:15:00

所以你可以做的是:

声明 bool 值 _isLoading =false;

您可以使用 setstate 来更改状态。

那么下面的代码是做什么的:

  1. 最初 _isLoading 将为 false,因此它将向您显示文本小部件。
  2. 当您点击登录按钮时,它会变为 true,因此会出现圆形进度指示器。
  3. 然后,当 api 调用完成后,将其重置回 false,这样我们就可以看到文本小部件了。
  4. 如果出现任何错误,则异常会使 _isLoading 为 false,以便它将成为文本小部件,并且将显示带有错误消息的对话框。

我已经获取了您的代码,只是进行了更改检查 bool 值的使用并根据您的状态管理需求使用它,我已经用一个简单的 setState 进行了详细说明。

class App extends StatelessWidget {

  bool _isLoading =false;

 @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return SizedBox(
      width: MediaQuery.of(context).size.width,
      child: TextButton(
        onPressed: signIn,
        style: ButtonStyle(
          padding: MaterialStateProperty.all<EdgeInsets>(
            const EdgeInsets.fromLTRB(0, 20, 0, 20),
          ),
          shape:
          MaterialStateProperty.all<RoundedRectangleBorder>(
              RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(30.0))),
          // backgroundColor:
          // MaterialStateProperty.all(primaryColor),
        ),
        child:

        _isLoading ?
        const CircularProgressIndicator():
        const Text(
          'Login',
          style: TextStyle(
            color: Colors.white,
            fontSize: 15,
            fontFamily: 'InterBold',
          ),
        ),
      ),
    );
  }
  Future signIn() async {

    if (_key.currentState!.validate()) {
      try {

        setState({
          _isLoading =true;
        });
        await FirebaseAuth.instance.signInWithEmailAndPassword(
            email: emailController.text.trim(),
            password: passwordCrontroller.text.trim());

        errorMessage = '';
        setState({
        _isLoading =false;
        });

      } on FirebaseAuthException catch (e) {
        setState({
        _isLoading =false;
        });
        showDialog(
            context: context,
            builder: (context) => AlertDialog(
              title: const Text(
                'Error',
                style: TextStyle(color: mainText),
              ),
              content: Text(
                e.message!,
                style: const TextStyle(color: secondaryText),
              ),
              contentPadding:
              const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
              backgroundColor: Colors.white,
              actions: [
                TextButton(
                    onPressed: () {
                      navigatorKey.currentState!.pop();
                    },
                    child: const Text(
                      'Close',
                      style: TextStyle(color: primaryColor),
                    ))
              ],
            ));
      }
    }
  }

}

让我知道它是否有效

So what you can do is the following :

declare the bool value _isLoading =false;

you can use the setstate to change the state.

So what does the below code do:

  1. Initially _isLoading will be false so it will show you the text widget.
  2. when you hit the signin button it will make it true so the circular progress indicator will be appearing.
  3. then when the api call is complete then resetting it back to false and that we can see the text widget.
  4. And if there comes any error en the exception making the _isLoading to false so that it will be the text widget and there will be dialog shown with error message.

I have taken your code and just made the changes check the use of bool value and use it as per you state management needs, I have elaborated with a simple setState.

class App extends StatelessWidget {

  bool _isLoading =false;

 @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return SizedBox(
      width: MediaQuery.of(context).size.width,
      child: TextButton(
        onPressed: signIn,
        style: ButtonStyle(
          padding: MaterialStateProperty.all<EdgeInsets>(
            const EdgeInsets.fromLTRB(0, 20, 0, 20),
          ),
          shape:
          MaterialStateProperty.all<RoundedRectangleBorder>(
              RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(30.0))),
          // backgroundColor:
          // MaterialStateProperty.all(primaryColor),
        ),
        child:

        _isLoading ?
        const CircularProgressIndicator():
        const Text(
          'Login',
          style: TextStyle(
            color: Colors.white,
            fontSize: 15,
            fontFamily: 'InterBold',
          ),
        ),
      ),
    );
  }
  Future signIn() async {

    if (_key.currentState!.validate()) {
      try {

        setState({
          _isLoading =true;
        });
        await FirebaseAuth.instance.signInWithEmailAndPassword(
            email: emailController.text.trim(),
            password: passwordCrontroller.text.trim());

        errorMessage = '';
        setState({
        _isLoading =false;
        });

      } on FirebaseAuthException catch (e) {
        setState({
        _isLoading =false;
        });
        showDialog(
            context: context,
            builder: (context) => AlertDialog(
              title: const Text(
                'Error',
                style: TextStyle(color: mainText),
              ),
              content: Text(
                e.message!,
                style: const TextStyle(color: secondaryText),
              ),
              contentPadding:
              const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
              backgroundColor: Colors.white,
              actions: [
                TextButton(
                    onPressed: () {
                      navigatorKey.currentState!.pop();
                    },
                    child: const Text(
                      'Close',
                      style: TextStyle(color: primaryColor),
                    ))
              ],
            ));
      }
    }
  }

}

Let me know if it works

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文