Ber*_*eam 240 dart flutter flutter-dependencies flutter-state flutter-build
我注意到我的项目中出现了新的 lint 问题。
长话短说:
我需要在我的自定义类中使用 BuildContext
flutter lint 工具与 aysnc 方法一起使用时并不满意。
例子:
MyCustomClass{
final buildContext context;
const MyCustomClass({required this.context});
myAsyncMethod() async {
await someFuture();
# if (!mounted) return; << has no effect even if i pass state to constructor
Navigator.of(context).pop(); # << example
}
}
Run Code Online (Sandbox Code Playgroud)
Gui*_*dem 279
更新 Flutter 3.7+:
mounted
属性现已正式添加到BuildContext
,因此您可以从任何地方检查它,无论它来自 StatefulWidget State 还是来自 Stateless widget。
虽然将上下文存储到外部类中仍然是一种不好的做法,但您现在可以在异步调用后安全地检查它,如下所示:
class MyCustomClass {
const MyCustomClass();
Future<void> myAsyncMethod(BuildContext context) async {
Navigator.of(context).push(/*waiting dialog */);
await Future.delayed(const Duration(seconds: 2));
if (context.mounted) Navigator.of(context).pop();
}
}
// Into widget
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: () => const MyCustomClass().myAsyncMethod(context),
icon: const Icon(Icons.bug_report),
);
}
// Into widget
Run Code Online (Sandbox Code Playgroud)
原答案
不要将上下文直接存储到自定义类中,如果您不确定您的小部件是否已安装,也不要在异步后使用上下文。
做这样的事情:
class MyCustomClass {
const MyCustomClass();
Future<void> myAsyncMethod(BuildContext context, VoidCallback onSuccess) async {
await Future.delayed(const Duration(seconds: 2));
onSuccess.call();
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: () => const MyCustomClass().myAsyncMethod(context, () {
if (!mounted) return;
Navigator.of(context).pop();
}),
icon: const Icon(Icons.bug_report),
);
}
}
Run Code Online (Sandbox Code Playgroud)
iDe*_*ode 100
context.mounted
*在StatefulWidget
/StatelessWidget
或任何具有以下特征的类中BuildContext
:
void foo(BuildContext context) async {
await someFuture();
if (!context.mounted) return;
Navigator.pop(context); // No warnings now
}
Run Code Online (Sandbox Code Playgroud)
* 如果你在 a 中StatefulWidget
,你也可以使用 justmounted
代替context.mounted
小智 40
如果你的课程可以StatefulWidget
从那时开始扩展
if (!mounted) return;
Run Code Online (Sandbox Code Playgroud)
会工作!
编辑
我一次又一次地遇到这个问题,这就是技巧 - 在使用异步方法之前使用或声明变量,context
如下所示:
MyCustomClass{
const MyCustomClass({ required this.context });
final buildContext context;
myAsyncMethod() async {
// Declare navigator instance (or other context using methods/classes)
// before async method is called to use it later in code
final navigator = Navigator.of(context);
await someFuture();
// Now use the navigator without the warning
navigator.pop();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑结束
根据Guildem的回答,他仍然使用
if (!mounted) return;
Run Code Online (Sandbox Code Playgroud)
那么添加更多带回调的意大利面条代码有什么意义呢?如果此async
方法必须将一些数据传递给您也传递的方法怎么办context
?那么我的朋友,你的桌子上将会有更多的意大利面和另一个额外的问题。
context
核心概念是触发 async bloc 后不使用;)
你可以使用这种方法
myAsyncMethod() async {
await someFuture().then((_){
if (!mounted) return;
Navigator.of(context).pop();
}
});
Run Code Online (Sandbox Code Playgroud)
现在,您可以从小部件中的任何位置以及使用 BuildContext 的任何类中的上下文中访问已安装的内容,如下所示
myAsyncMethod() async {
await someFuture().then((_){
if (!mounted) return;
Navigator.of(context).pop();
}
});
Run Code Online (Sandbox Code Playgroud)
小智 9
如果您想在无状态小部件中使用安装检查,可以通过在 BuildContext 上进行扩展来实现
extension ContextExtensions on BuildContext {
bool get mounted {
try {
widget;
return true;
} catch (e) {
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它
if (context.mounted)
Run Code Online (Sandbox Code Playgroud)
此功能的灵感来自GitHub PR ,并且在合并的 PR 中通过了相同的测试
这对我有帮助。
/// transition to the main page after a pause of 3 seconds
Future<void> _navigateToMainScreen(BuildContext context) async {
await Future.delayed(const Duration(seconds: 3));
if (context.mounted) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => const MainScreen()));
}
}
Run Code Online (Sandbox Code Playgroud)
在 Flutter 3.7.0 中BuildContext
具有该属性mounted
。它可以在 StatelessWidget 和 StatefulWidget 中使用,如下所示:
void bar(BuildContext context) async {
await yourFuture();
if (!context.mounted) return;
Navigator.pop(context);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
159094 次 |
最近记录: |