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

Flutter调用showDialog遇空检查错误:如何传递有效Context?

Flutter调用showDialog时出现Null check空值错误的解决方法

错误信息

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
#0      Navigator.of (package:flutter/src/widgets/navigator.dart:2794)
#1      showDialog (package:flutter/src/material/dialog.dart:1425)
#2      MyAppState.showMessage (package:simple_sensor_test/main.dart:45)
#3      MyAppState.build.<anonymous closure> (package:simple_sensor_test/main.dart:30)
#4      _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1170)
#5      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:351)
#6      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:656)
#7      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:313)
#8      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:246)
#9      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:703)
#10     PointerRouter._dispatch (package:flutter/src/g<…>

完整代码

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Testing'),
        ),
        body: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Row( // need upright vector, new lat, new lon
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  ElevatedButton(
                    onPressed: () { showMessage("Hello", "world"); },
                    child: const Text('Calculate'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> showMessage(String title, String message) async {
    // Ensure the widget is still mounted and context is valid
    if (mounted) {
      showDialog(
          context: context,
          builder: (context) =>
              const Center(
                child: Material(
                  color: Colors.transparent,
                  child: Text('Message'),
                ),
              )
      );
    }
  }
}

问题核心

原本认为State对象继承的Context是有效的,但调用Navigator相关函数时出现空值错误,如何向showDialog传递有效的Context?

解决方法

原因分析

你当前使用的context是MyAppState的上下文,而MyApp直接作为runApp的参数,这个上下文不在MaterialApp的导航器树中。showDialog需要的是能找到Navigator的上下文,也就是MaterialApp内部的上下文。

两种修复方案

  • 方案1:拆分Widget结构,将MaterialApp移出StatefulWidget
    把MaterialApp放在顶层,让StatefulWidget作为它的子组件,这样State拿到的上下文就处于导航器树中:
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Testing'),
      ),
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                ElevatedButton(
                  onPressed: () { showMessage("Hello", "world"); },
                  child: const Text('Calculate'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Future<void> showMessage(String title, String message) async {
    if (mounted) {
      showDialog(
          context: context,
          builder: (context) =>
              AlertDialog(
                title: Text(title),
                content: Text(message),
                actions: [
                  TextButton(
                    onPressed: () => Navigator.pop(context),
                    child: const Text('确定'),
                  )
                ],
              )
      );
    }
  }
}
  • 方案2:给MaterialApp设置GlobalKey,通过key获取导航器上下文
    如果不想调整Widget结构,可以给MaterialApp设置全局Key,通过key.currentContext获取有效导航上下文:
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: _navigatorKey,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Testing'),
        ),
        body: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  ElevatedButton(
                    onPressed: () { showMessage("Hello", "world"); },
                    child: const Text('Calculate'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> showMessage(String title, String message) async {
    if (mounted) {
      showDialog(
          context: _navigatorKey.currentContext!,
          builder: (context) =>
              AlertDialog(
                title: Text(title),
                content: Text(message),
                actions: [
                  TextButton(
                    onPressed: () => Navigator.pop(context),
                    child: const Text('确定'),
                  )
                ],
              )
      );
    }
  }
}

额外优化

原代码中showDialog的builder返回简单Text,建议改成标准AlertDialog组件,既符合Material设计规范,也能正常关闭弹窗。


内容的提问来源于stack exchange,提问作者Graeme Burton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:50:02