我在做项目时遇到了一个问题。 我正在尝试通过 API 将医生注册到数据库。当我单击注册按钮时,我希望它显示一个加载对话框以等待 API 响应,然后如果发生错误,我想显示一个错误对话框。
但是当我尝试关闭(单击错误对话框上的“确定”按钮)错误对话框时,它会从父小部件或当前页面弹出,它会删除该页面。
以下是我尝试过的示例。
1- 用户提供商;
showDialog()
方法或showSnackbar
方法,它需要返回一个小部件。此链接是要运行和编辑的 Dartpad 示例:https://dartpad.dev/?id=87bd2aae2f549c10201c02996fd1e10f
以下是我尝试过的示例。
1- 主要方法和主页:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => UserProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/',
routes: {
'/': (context) => const MyHomePage(title: 'Flutter Demo Home Page'),
},
),
),
);
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late UserProvider _userProvider;
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context, listen: true);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer<UserProvider>(
builder: (context, notifire, child) {
if (notifire.state == NotifireState.initial) {
return const Text(
'Click To Register',
style: TextStyle(
fontSize: 16,
height: 1.3,
),
);
} else if (notifire.state == NotifireState.loading) {
return const LoadingDialog(message: 'Wait for Response...');
} else {
//return const RegistrationSucceededDialog();
return const RegistrationErrorDialog(
errorMessage: 'problem Message',
);
}
},
),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
//Provider.of<UserProvider>(context, listen: true).registerUser('User');
_userProvider.registerUser('User');
},
child: const Text(
'Register',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w400,
),
),
),
],
),
),
);
}
}
2- 用户提供商:
enum NotifireState { initial, loading, loaded }
class UserProvider extends ChangeNotifier {
//final AbstractHttpUserRepo _httpUserService = HttpUserService();
NotifireState _state = NotifireState.initial;
NotifireState get state => _state;
void _setState(NotifireState state) {
_state = state;
notifyListeners();
}
// // One User
late User _user;
User get user => _user;
void _setUser(
User user,
) {
_user = user;
}
// // Multiple Users
late User _users;
User get users => _users;
void _setUsers(
User users,
) {
_users = users;
}
Future<void> registerUser(
User user,
) async {
_setState(NotifireState.loading);
// // call the api to register
// final userCreateResult = await _httpUserService.create(user);
await Future.delayed(const Duration(seconds: 3));
// // Set the user
// _setDoctor(userCreateResult);
_setState(NotifireState.loaded);
}
}
3-错误对话框无状态小部件:
class RegistrationErrorDialog extends StatelessWidget {
final String errorMessage;
const RegistrationErrorDialog({
Key? key,
required this.errorMessage,
}) : super(key: key);
final TextStyle _buttonsTextStyle = const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w400,
);
final TextStyle _textStyle = const TextStyle(
height: 1.3,
fontSize: 16.7,
fontWeight: FontWeight.w500,
);
@override
Widget build(BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
insetPadding: const EdgeInsets.symmetric(horizontal: 15),
icon: const Icon(
Icons.error_rounded,
size: 45,
color: Colors.red,
),
iconPadding: const EdgeInsets.only(top: 5, bottom: 10),
actionsPadding: const EdgeInsets.only(right: 15, bottom: 10),
content: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'An Error Occurred While Registrating The Accout:',
style: _textStyle,
),
const SizedBox(height: 20),
Text(
errorMessage,
// softWrap: false,
style: _textStyle,
),
],
),
actions: [
TextButton(
child: Text(
'Ok',
style: _buttonsTextStyle,
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
}
4- 和加载对话框:
class LoadingDialog extends StatelessWidget {
final String message;
const LoadingDialog({
Key? key,
required this.message,
}) : super(key: key);
final TextStyle _textStyle = const TextStyle(
height: 1.3,
fontSize: 16.7,
fontWeight: FontWeight.w500,
);
@override
Widget build(BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
insetPadding: const EdgeInsets.symmetric(horizontal: 15),
iconPadding: const EdgeInsets.only(top: 5, bottom: 10),
actionsPadding: const EdgeInsets.only(right: 15, bottom: 10),
content: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 10),
Text(
message,
style: _textStyle,
),
],
),
);
}
}
您无法将小部件返回为
AlertDialog
。这不是如何使用和显示对话框。
阅读这个官方示例:https://api.flutter.dev/flutter/material/AlertDialog-class.html
你必须使用
showDialog
方法,然后使用其中的AlertDialog
。
showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('AlertDialog Title'),
content: const Text('AlertDialog description'),
actions: <Widget>[]
showDialog
是未来的方法。和 Navigator.pop
将关闭该对话框。
如果您在没有该方法的情况下关闭 AlertDialog
,则您将使用空堆栈导航路线。这就是为什么然后没有显示。