[英]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 的新手,想知道如何使用async
和await
。
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.