简体   繁体   English

不要跨异步间隙使用 BuildContexts flutter

[英]Do not use BuildContexts across async gaps flutter

I've made a function for registration and I'm getting a warning Do not use BuildContexts across async gaps.我已经注册了一个 function 并且我收到警告Do not use BuildContexts across async gaps. on Utils.flushBarErrorMessage("No Inte.net", context);关于Utils.flushBarErrorMessage("No Inte.net", context); I'm new to flutter and want to know how to use async and await .我是 flutter 的新手,想知道如何使用asyncawait

Future _registration() async {
    String name = _nameController.text.trim();
    String email = _emailController.text.trim();
    String password = _passwordController.text.trim();
    String phone = _phoneController.text.trim();

    if (name.isEmpty) {
      Utils.flushBarErrorMessage("Type your name", context);
    } else if (email.isEmpty) {
      Utils.flushBarErrorMessage("Type your email", context);
    } else if (!GetUtils.isEmail(email)) {
      Utils.flushBarErrorMessage("Type valid email address", context);
    } else if (password.isEmpty) {
      Utils.flushBarErrorMessage("Type your password", context);
    } else if (password.length < 6) {
      Utils.flushBarErrorMessage(
          "password can't be less than 6 characters", context);
    } else if (phone.isEmpty) {
      Utils.flushBarErrorMessage("Type your phone", context);
    }
    else {
      var connectivityResult = await (Connectivity().checkConnectivity());
      if (connectivityResult == ConnectivityResult.mobile ||
          connectivityResult == ConnectivityResult.wifi) {
        ApiCall.signUp(name, email, password, phone).then((value) {
          if (value.statusCode == 200) {
            if (json.decode(value.body)['success'] != null) {
              if (json.decode(value.body)["success"]) {
                RegisterResponse registerResponseModel =
                    RegisterResponse.fromJson(json.decode(value.body));
                Navigator.pushNamed(context, VerifyUser.routeName);
                Utils.flushBarErrorMessage(
                    'User Registered Successfully', context);
                if (kDebugMode) {
                  print('User Registered Successfully');
                }
              } else {
                Utils.flushBarErrorMessage(
                    json.decode(value.body)["en_message"], context);
                if (kDebugMode) {
                  print(json.decode(value.body).toString());
                }
              }
            }
          } else {
            Utils.flushBarErrorMessage('invalid data', context);
            if (kDebugMode) {
              print(json.decode(value.body).toString());
            }
          }
        });
      } else {
        Utils.flushBarErrorMessage("No Internet", context);
      }
    }
  }

calling this _registration()调用这个_registration()

ElevatedButton(
            onPressed: () {
              _registration();
            },
            child: const Text('SignUp')),

Here is my flushBarErrorMessage .这是我的flushBarErrorMessage

   class Utils {
  static void flushBarErrorMessage(String message, BuildContext context) {
    showFlushbar(
        context: context,
        flushbar: Flushbar(
          forwardAnimationCurve: Curves.decelerate,
          margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
          padding: const EdgeInsets.all(15),
          titleColor: Colors.white,
          duration: const Duration(seconds: 3),
          borderRadius: BorderRadius.circular(10),
          reverseAnimationCurve: Curves.easeInOut,
          icon: const Icon(
            Icons.error,
            size: 28,
            color: Colors.white,
          ),
          flushbarPosition: FlushbarPosition.TOP,
          positionOffset: 20,
          message: message,
          backgroundColor: Colors.red,
        )..show(context));
  }
}

Try this:尝试这个:

///Add context
Future _registration(BuildContext context) async {
...
if(!mounted) return;
 Navigator.pushNamed(context, VerifyUser.routeName);
...
}

When calling:调用时:

ElevatedButton(
            onPressed: () {
             //make sure your class is of StatefulWidget()
              _registration(context); ///Add context
            },
            child: const Text('SignUp')),

The problem is that after an await , every use of the BuildContext will show this warning.问题是在await之后,每次使用BuildContext都会显示此警告。 This warning happens because using a BuildContext after an await could happen after the widget is disposed of.发生此警告是因为在处理小部件后可能会在await后使用BuildContext This way, the context wouldn't exist anymore and the app could even crash because of this.这样,上下文将不再存在,应用程序甚至可能因此崩溃。 Check out the official lint documentation :查看官方 lint 文档

Storing BuildContext for later usage can easily lead to difficult-to-diagnose crashes.存储 BuildContext 以供以后使用很容易导致难以诊断的崩溃。 Asynchronous gaps are implicitly storing BuildContext and are some of the easiest to overlook when writing code.异步间隙隐式存储 BuildContext 并且是编写代码时最容易忽略的部分。

The easy solution, from the official docs, is the need to check for State.mounted .来自官方文档的简单解决方案是需要检查State.mounted The code would look something like this on every place the warning shows up:在警告出现的每个地方,代码看起来都像这样:

      ...
      } else {
        if (mounted) Utils.flushBarErrorMessage("No Internet", context);
      }
      ...

The simplest answer for this warning is:此警告的最简单答案是:

StatelessWidget

keep a reference of the context usage before the await keyword.await关键字之前保留context用法的引用。

example:例子:

// navigation
onPressed: () async {
    final router = GoRouter.of(context);

    final result = await [
        Permission.location,
        Permission.locationAlways,
        Permission.locationWhenInUse
    ].request();

    if (...) {
        router.go(AppRouter.dashboard);
    } else {
        router.go(AppRouter.askForCustomLocation);
    }

// cubit
onPressed: () async {

    final appSettingsCubit = BlocProvider.of<AppSettingsCubit>(context);

    final result = await [
        Permission.location,
        Permission.locationAlways,
        Permission.locationWhenInUse
    ].request();

    if (...) {
        appSettingsCubit.locationProptAsked();
    } else {
        appSettingsCubit.locationProptAsked();
    }

StatefullWidget

just wrap the context usage with a if(mounted) logic只需用if(mounted)逻辑包装context使用

example:例子:

// navigation
onPressed: () async {    
    final result = await [
        Permission.location,
        Permission.locationAlways,
        Permission.locationWhenInUse
    ].request();

    if (...) {
        if(mounted) {
            router.go(AppRouter.dashboard);
        }
    } else {
        if(mounted) {
            router.go(AppRouter.dashboard);
        }
    }

// cubit
onPressed: () async {
    final result = await [
        Permission.location,
        Permission.locationAlways,
        Permission.locationWhenInUse
    ].request();

    if (...) {
        if(mounted) {
            BlocProvider.of<AppSettingsCubit>(context).locationProptAsked();
        }
    } else {
        if(mounted) {
            BlocProvider.of<AppSettingsCubit>(context).locationProptAsked();
        }
    }

That's all from my experience.这都是我的经验。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter “不要跨异步间隙使用 BuildContexts” - Flutter "Do not use BuildContexts across async gaps" flutter 警告不要跨异步间隙使用 BuildContexts - flutter warning Do not use BuildContexts across async gaps 不要跨异步间隙使用 BuildContexts - Do not use BuildContexts across async gaps 不要跨异步间隙使用 BuildContexts。 将 pub yaml 更新到主要版本后 - Do not use BuildContexts across async gaps. After update pub yaml to the major version 在 flutter 中使用 Snack Bar 和 Navigator 时,如何修复“不要使用 BuildContexts accros async gaps” - How do I fix "Do not use BuildContexts accros async gaps" when using Snack Bar and Navigator in flutter 跨异步间隙的 BuildContexts,有什么替代方法? - BuildContexts across Async gaps, what is the alternative to this? 跨同步间隙的 BuildContexts 问题 - Problem with BuildContexts across sync gaps 如何解决 Riverpod 的 ConsumerWidget 中的“不要跨异步间隙使用 BuildContext”? - How to solve "Do not use BuildContext across async gaps" in Riverpod's ConsumerWidget? Gridview Flutter - 宽间隙 - Gridview Flutter - wide gaps Flutter:修改 Scaffold 以跟踪当前显示的 Scaffolds 的 BuildContexts 以用于应用程序范围的 SnackBar 方法 - Flutter: Modifying Scaffold to track currently displayed Scaffolds' BuildContexts for app-wide SnackBar methods
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM