Flutter中closeStatusWindow回调函数未执行问题排查
问题:为什么回调函数
void closeStatusWindow()无法执行? 我将回调函数void closeStatusWindow()作为onClose参数传入StatusWindow类,在StatusWindow的hide方法中调用onClose,但该回调并未执行。完整代码如下:
import 'package:flutter/material.dart'; void main() { runApp(const MainApp()); } class MainApp extends StatelessWidget { const MainApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: Scaffold( body: SafeArea( child: Padding( padding: EdgeInsets.symmetric(horizontal: 12), child: RegisterForm(), ), ), ), ); } } class RegisterForm extends StatefulWidget { const RegisterForm({super.key}); @override RegisterFormState createState() { return RegisterFormState(); } } class RegisterFormState extends State<RegisterForm> { final _formKey = GlobalKey<FormState>(); final _nameController = TextEditingController(); final _familynameController = TextEditingController(); void closeStatusWindow() { print('Executing closeStatusWindow');//This is not executing. Navigator.pop(context); } @override Widget build(BuildContext context) { return Form( key: _formKey, child: ListView( children: <Widget>[ const Text('Register'), const SizedBox(height: 10.0), TextFormField( controller: _nameController, decoration: InputDecoration( labelText: 'Name', border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your name'; } return null; }, ), const SizedBox(height: 15.0), TextFormField( controller: _familynameController, decoration: InputDecoration( labelText: 'Family name', border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your family name'; } return null; }, ), const SizedBox(height: 15.0), Align( child: ElevatedButton( onPressed: () async { _createAccount(context); }, style: ElevatedButton.styleFrom( elevation: 8.0, fixedSize: const Size(220.0, 30.0), ), child: const Text('Submit'), ), ), ], ), ); } _createAccount(BuildContext context) async { final data = { 'name': _nameController.text.trim(), 'family_name': _familynameController.text.trim(), }; UserModelEmulator userModel = UserModelEmulator(); userModel.save(data); StatusWindow( context: context, userModel: userModel, onClose: closeStatusWindow, ); } } class UserModelEmulator with ChangeNotifier { late Future<bool> result; void save(data) async { result = Future.delayed(const Duration(seconds: 3), () => true); notifyListeners(); } Future<bool> getFuture() { return result; } } typedef CloseStatusWindow = bool Function(); @immutable class StatusWindowController { final CloseStatusWindow close; // to closs our dialog const StatusWindowController({ required this.close, }); } class StatusWindow { StatusWindow({ required this.context, required this.userModel, required this.onClose, }) { _controller = showOverlay( context: context, ); } final BuildContext context; final UserModelEmulator userModel; final VoidCallback onClose; StatusWindowController? _controller; void hide() { _controller?.close(); _controller = null; onClose; } StatusWindowController? showOverlay({ required BuildContext context, }) { final state = Overlay.of(context); final renderBox = context.findRenderObject() as RenderBox; final size = renderBox.size; final overlay = OverlayEntry( builder: (context) { return Material( color: Colors.black.withAlpha(150), child: Center( child: Container( constraints: BoxConstraints( maxWidth: size.width * .8, maxHeight: size.width * .8, minWidth: size.width * .5, ), decoration: BoxDecoration( //color: Colors.white, border: Border.all( color: Theme.of(context).primaryColorLight, width: 3, ), borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 10), ListenableBuilder( listenable: userModel, builder: (BuildContext context, Widget? child) { return FutureBuilder<bool>( future: userModel.getFuture(), builder: (BuildContext context, AsyncSnapshot snapshot) { Widget icon; String message = ''; bool enableButton = false; if (snapshot.connectionState == ConnectionState.waiting) { icon = const CircularProgressIndicator(); message = 'Creating your account'; } else if (snapshot.hasError) { icon = const Icon( Icons.cancel_rounded, color: Colors.red, ); message = 'Failed to create your account'; enableButton = true; } else { icon = const Icon( Icons.check_circle, size: 30, color: Colors.green, ); message = 'Account created'; enableButton = true; } return Column( children: [ SizedBox( width: 50, height: 50, child: icon, ), const SizedBox(height: 10), Text(message), const SizedBox(height: 10), OutlinedButton( onPressed: enableButton ? hide : null, child: const Text('Close'), ), ], ); }, ); }, ), ], ), ), ), ), ); }, ); state.insert(overlay); return StatusWindowController( close: () { overlay.remove(); return true; }, ); } }
解决方法
核心问题是你在StatusWindow的hide方法中只是引用了onClose变量,没有实际调用这个函数。
错误代码片段:
void hide() { _controller?.close(); _controller = null; onClose; // 仅访问变量,未执行函数 }
修改后的代码:
void hide() { _controller?.close(); _controller = null; onClose(); // 添加括号,执行回调函数 }
另外补充一个潜在优化点:在RegisterFormState的_createAccount方法中,你创建了StatusWindow实例但未保存引用,虽然当前逻辑下Overlay能正常显示,但如果后续需要主动调用hide方法会找不到实例,建议保存引用:
StatusWindow? _statusWindow; _createAccount(BuildContext context) async { // ... 其他代码 _statusWindow = StatusWindow( context: context, userModel: userModel, onClose: closeStatusWindow, ); }
内容的提问来源于stack exchange,提问作者Jaimitove
相关产品推荐
相关产品推荐

