flutter - 对话框打开有延迟,在生成对话框之前导航到另一个视图时出现错误。我怎样才能让它不被生成?
问题描述
我是新来的。
在我真正的问题中,我的客户端经常出现在互联网非常慢的地方,所以有时会尝试发出网络请求,这可能需要一些时间,所以用户在网络请求之前离开屏幕完全的。有时,我的应用在完成 Web 请求后会生成一个dialog
. 所以这就是我的问题所在,用户正在尝试发出网络请求,完成后,他们离开屏幕然后dialog
生成。
我正在尝试使用delay
稍后生成dialog
.
我没有考虑结束网络请求的任何策略,我想要的是找到一种方法,一旦我离开屏幕,就不会生成对话框dispose
我举了一个例子,我有 2 个屏幕。在第二个屏幕上,单击按钮时会生成一个延迟 5 秒的对话框。如果在打开对话框之前导航到另一个屏幕,我会收到错误消息。我认为发生这种情况是因为视图被破坏,因此无法打开对话框。
在另一个视图中生成对话框时,我该怎么做才能避免该错误?如果我在另一个视图中,我不希望生成对话框。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("main");
return MaterialApp(title: 'Provider Example', initialRoute: '/', routes: {
'/': (context) => Home(),
'home': (context) => Home(),
'dialogpage': (context) => Dialogpage(),
});
}
}
class Home extends StatelessWidget {
Home() {
print("home");
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('home'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_alert),
tooltip: 'Show Snackbar',
onPressed: () {
Navigator.pushNamed(context, "dialogpage");
},
),
],
),
body: const Center(
child: Text(
'home',
style: TextStyle(fontSize: 24),
),
),
);
}
}
class Dialogpage extends StatelessWidget {
Dialogpage() {
print("dialogpage");
}
dialog(BuildContext context) {
Future.delayed(const Duration(seconds: 5), () {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
title: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(19.0),
topRight: Radius.circular(19.0),
),
),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5),
child: Text(
'Error',
style: TextStyle(color: Colors.white),
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 20.0, bottom: 20.0),
child: Icon(
Icons.error,
size: 50,
),
),
Text("dialog"),
],
),
titlePadding: EdgeInsets.all(0),
actions: <Widget>[
FlatButton(
child: Text('Aceptar'),
onPressed: () {
return Navigator.of(context).pop();
}),
],
);
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('dialog'),
),
body: Center(
child: RaisedButton(
child: Text("show dialog"),
onPressed: () {
dialog(context);
}),
),
);
}
}
解决方案
而不是Future.delayed
,您应该使用Timer
,它可以在onDispose
方法中取消。
工作解决方案:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("main");
return MaterialApp(
title: 'Provider Example',
initialRoute: '/',
routes: {
'/': (context) => Home(),
'home': (context) => Home(),
'dialogpage': (context) => Dialogpage(),
},
);
}
}
class Home extends StatelessWidget {
Home() {
print("home");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('home'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_alert),
tooltip: 'Show Snackbar',
onPressed: () {
Navigator.pushNamed(context, "dialogpage");
},
),
],
),
body: const Center(
child: Text(
'home',
style: TextStyle(fontSize: 24),
),
),
);
}
}
class Dialogpage extends StatefulWidget {
@override
_DialogpageState createState() => _DialogpageState();
}
class _DialogpageState extends State<Dialogpage> {
Timer _timer;
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
dialog(BuildContext context) {
_timer = Timer(
const Duration(seconds: 3),
() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
title: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(19.0),
topRight: Radius.circular(19.0),
),
),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5),
child: Text(
'Error',
style: TextStyle(color: Colors.white),
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 20.0, bottom: 20.0),
child: Icon(
Icons.error,
size: 50,
),
),
Text("dialog"),
],
),
titlePadding: EdgeInsets.all(0),
actions: <Widget>[
FlatButton(
child: Text('Aceptar'),
onPressed: () {
return Navigator.of(context).pop();
},
),
],
);
},
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('dialog'),
),
body: Center(
child: RaisedButton(
child: Text("show dialog"),
onPressed: () {
dialog(context);
},
),
),
);
}
}
推荐阅读
- amazon-web-services - AWS 资源消失
- nvidia - NVIDIA SDK Manager 无法在 Jetson Xavier NX 上安装
- python - Simultaneous reads of the same PyTorch torchvision.datasets object
- google-cloud-platform - 如何解决 Apache-Beam 中的 BeamDeprecationWarning
- html - 如何摆脱 CSS 中按钮之间不必要的空间
- node.js - mongodb 中是否有任何内置方法来更新 mongodb 文档中的数组
- drools - Drools 规则左侧的“this”等效关键字
- javascript - switch / if-elseif-else 函数是否应该有一个默认情况,如果在处理程序中没有匹配和处理的情况,则返回 null ?
- rust - 从 Rust BTreeMap 中删除一个范围
- arrays - 大型数组的基本 cuBLAS 点积返回不正确的值