You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:24:51