在我的Flutter应用程序中,我有一个按钮,该按钮启动了异步网络操作,并在等待它完成时显示对话框。完成后,对话框将从导航中弹出,但是我遇到了并发问题。这是我的代码:
ElevatedButton(
onPressed: () async {
showDialog(
context: context,
builder: (context) => Center(child: CircularProgressIndicator()),
);
await asyncNetworkOperation();
Navigator.pop(context);
},
child: Text("Press here");
)
如果在进行网络操作时,用户点击了Android返回按钮,则对话框会提前弹出。然后,一旦网络操作完成,就会发出另一个Navigator.pop(上下文),从而将导航推回一个额外的步骤。
如果用户已经弹出对话框,则避免执行导航器的最佳方法是什么?我知道我可以防止返回按钮与 willPopsCope
窗口小部件完全工作,但是我希望用户能够在操作中花费太长时间能够中止该操作。
TLDR:如何在异步效果中预防 navigator.pop()
,以弹出已经弹出的路由?
In my flutter application I have a button which starts an asynchronous network operation and displays a dialog while waiting for it to complete. Once completed, the dialog is popped from the navigation, but I am running into concurrency issues. Here's my code:
ElevatedButton(
onPressed: () async {
showDialog(
context: context,
builder: (context) => Center(child: CircularProgressIndicator()),
);
await asyncNetworkOperation();
Navigator.pop(context);
},
child: Text("Press here");
)
If the user taps on the Android back button while the network operation is in progress, the dialog gets popped ahead of time. And then, once the network operation completes, another Navigator.pop(context) is issued which pushes the navigation back one extra step.
What is the best way to avoid Navigator.pop from executing if the user already popped the dialog? I know I could prevent the back button from working altogether with the WillPopScope
widget, but I would like the user to have the ability to abort the operation should it take too long.
TLDR: How to prevent a Navigator.pop()
in an async frunction from popping a route which has already been popped?
发布评论
评论(4)
一种多功能方法(可能是建议)正在使用已安装的属性,该属性需要您使用
statefulwidget
:创建,框架通过将其与
state> state
object和nated code> initstatebuildContext
关联来“安装”状态对象。状态
对象保持安装直到框架调用处置
,此后,框架将永远不会要求state> state
对象再次构建,因此您可以在安全使用上下文对象之前,请检查已安装的
属性,除了弹出导航器外,其他目的。See:
A versatile approach (and probably recommended) is using the mounted property, which would require you to use a
StatefulWidget
:After creating a
State
object and before callinginitState
, the framework "mounts" the State object by associating it with aBuildContext
. TheState
object remains mounted until the framework callsdispose
, after which time the framework will never ask theState
object to build again, therefore you can check themounted
property before safely using the context object, for other purposes other than just popping the navigator as well.See:
您可以检查对话框是否活动。仅在有主动对话框
示例时返回:
You could check if the dialog is active or not. Only go back if there is active dialog
Example:
可以使用 statefulwidget 来解决此问题。我们可以使用已安装 statefulwidget的属性来检查小部件是否处置。无状态宽松没有安装的属性。
This issue can be solved by using the StatefulWidget. We can use mounted property of a StatefulWidget to check wether the widget is disposed or not. There is no mounted property in StatelessWidget.
不确定,如果这很有意义。
如果我没有错,这是在检查给定上下文的路线当前位于导航器树的顶部。如果是流行音乐,否则不要弹出。在此示例中,我通过的上下文属于对话框。我使用的另一种方式是确保对话框下的小部件不在顶部。
无效的安全性,取决于您,我将“!= true”放置,因为如果它的空,我也不想弹出。无论出于何种原因,WidgetContext的ModalRoute都不会返回我的价值。与为什么我使用“?false”相同
Not sure, if this make sense.
If I am not wrong, this is checking the route of the given context is currently on the top of the navigator tree. If it is pop, else dont pop. In this example the context i pass belongs to the dialog. The other way i used was to make sure that the widget under my dialog is not at the top.
Null safety, is up to you, I put "!= true" because if its null i do not want to pop as well. for whatever reason the ModalRoute for the widgetContext does not return me a value. same as why i use "?? false"