英文:
Is the warning "Don't use 'BuildContext's across async gaps" a useless warning?
问题
考虑这个第一个例子:
Future<void> initializeServices() async {
await notificationService.begin();
await geotrackingService.begin();
Navigator.of(context).pop(); // 不要在异步间隙中使用 'BuildContext'。
}
现在,考虑这个第二个例子:
Future<void> initializeServices() async {
await notificationService.begin();
await geotrackingService.begin();
exitScreen();
// exitScreenAsync();
}
void exitScreen() {
Navigator.of(context).pop(); // 现在编译器满意了。
}
Future<void> exitScreenAsync() async {
Navigator.of(context).pop(); // 编译器仍然满意吗?
}
正如您所看到的,这两个例子之间唯一的区别是第二个例子通过调用函数来弹出导航器,而第一个例子没有。然而,在第二个例子中,编译器是完全满意的,没有显示任何警告。
我觉得这个警告有点愚蠢和无意义。为什么我必须将使用 'BuildContext' 的代码部分移动到一个代理函数中,只是为了摆脱这个警告呢?
英文:
Consider this first example:
Future<void> initializeServices() async {
await notificationService.begin();
await geotrackingService.begin();
Navigator.of(context).pop(); // Don't use 'BuildContext's across async gaps.
}
Now, consider this second example:
Future<void> initializeServices() async {
await notificationService.begin();
await geotrackingService.begin();
exitScreen();
// exitScreenAsync();
}
void exitScreen() {
Navigator.of(context).pop(); // The compiler is satisfied now.
}
Future<void> exitScreenAsync() async {
Navigator.of(context).pop(); // The compiler remains satisfied?
}
As you can see, the only difference between these two examples is that the the second example is popping the navigator by calling a function while the first one is not. However, with the second exmaple the compiler is perfectly fine and no warning is displayed.
I find this warning a bit stupid and meaningless. Why do I have to move the code section that makes use of the BuildContext
across async gaps to a proxy function just to get rid of this warning?
答案1
得分: 1
这个警告并不是无用的警告。
问题是,在等待后,每次使用 BuildContext 都会显示这个警告。这个警告之所以出现是因为在等待之后使用 BuildContext 可能会在小部件被销毁后发生。这种情况下,上下文将不再存在,应用甚至可能因此崩溃。请查看官方的 lint 文档:
if (context.mounted) Navigator.of(context).pop();
英文:
No it's not useless warning.
The problem is that after an await, every use of the BuildContext will show this warning. This warning happens because using a BuildContext after an await could happen after the widget is disposed of. This way, the context wouldn't exist anymore and the app could even crash because of this. Check out the official lint documentation:
if (context.mounted) Navigator.of(context).pop();
答案2
得分: 0
你不应该忽略这个警告,因为它可能导致运行时错误。在异步函数期间,小部件可能会被卸载或销毁,导致无效的构建上下文。
在异步调用之后,并在使用 context
之前,每次都要检查小部件是否已挂载,像这样:
Future<void> initializeServices() async {
await notificationService.begin();
await geotrackingService.begin();
if (mounted) {
Navigator.of(context).pop();
}
}
警告将消失,但这次您将受到保护,不会使用无效的上下文。要使用 mounted
,您必须位于具有此属性的小部件类内部。
英文:
You should not ignore this warning because it can lead to a runtime error. During the async function the widget can be dismounted or destroyed, resulting in an invalid build context.
Check if the widget is mounted after the async calls and before using the context
every time, like this:
Future<void> initializeServices() async {
await notificationService.begin();
await geotrackingService.begin();
if (mounted) {
Navigator.of(context).pop();
}
}
The warning will disappear but this time you are protected against using an invalid context. In order to use mounted
you must be inside a widget class which has this property.
答案3
得分: 0
你的 exitScreen
不是一个 async
方法,这就是为什么编译器满意的原因。initializeServices()
是一个 async
方法,它包含一些未来需要等待的内容,然后才能使用上下文来退出,这就是为什么它在抱怨。
如果你仍然希望使用 exitScreen
,最好检查是否已挂载,如下所示:
if (mounted) exitScreen();
英文:
Your exitScreen
is not an async
method, that's why compiler is satisfied. The initializeServices()
is an async
method, it contains some future to be awaited before it can use context to pop, that's why it was complaining.
If you still wish to use exitScreen
it would be proper to check mounted like
if(mounted) exitScreen();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论