跳到主要内容

flutter awai后不能使用context问题解析

管

管理员

flutter

2022年11月17日 3,079 次阅读
本页目录

awai后不能使用context问题解析 报错:Do not use BuildContexts across async gaps.

理解这个问题需要明白 context和widget的对应关系,context和wididget一对一对应,一个context对应一个widget,不明白可以哔哩哔哩搜索王叔不是秃子中有专门讲解..

问题从以下代码中备注解释

// From SO answer
// https://stackoverflow.com/a/69512692/10476111

import 'dart:async';

import 'package:flutter/material.dart';

class TestPage extends StatelessWidget {
  const TestPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home Page')),
      body: Center(
        child: ElevatedButton(
          child: Text('Open Test Page'),
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (_) => TestCon()),
            );
          },
        ),
      ),
    );
  }
}

class TestCon extends StatefulWidget {
  @override
  State<TestCon> createState() => _TestConState();
}

class _TestConState extends State<TestCon> {
  late final Timer timer;

  @override
  void initState() {
    super.initState();
    timer = Timer.periodic(Duration(milliseconds: 500), (timer) {
      setState(() {});
    });
  }

  @override
  void dispose() {
    timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final time = DateTime.now().millisecondsSinceEpoch;
    return Scaffold(
      appBar: AppBar(title: Text('Test Page')),
      body: Center(
        child: Column(
          children: [
            Text('Current Time: $time'),
            MySafeButton(key: UniqueKey()),
            MyDangerousButton(key: UniqueKey()),
          ],
        ),
      ),
    );
  }
}

class MySafeButton extends StatelessWidget {
  const MySafeButton({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      child: Text('Open Dialog Then Pop Safely'),
      onPressed: () async {
//当像下面的MyDangerousButton那样不先把(Navigator.of(context)[备注Navigator.of(context)其实就是context对应的widiget])存储时候,
//因为await原因,因为是异步方法,所以await回来后可能context已经被flutter丢弃(initState中的代码传入UniqueKey一直刷新)
//所以会报错旧context已经被丢弃,使用丢弃的context中自然会报错
        final navigator = Navigator.of(context);  
        await showDialog(
          context: context,
          
          builder: (_) => AlertDialog(            //注意这里的build传入的是_
            title: Text('Dialog Title'),
            actions: [
              TextButton(onPressed: () {
                navigator.pop();       
                //当执行这条语句时,实际上也是在TestCon中查找存在的dialog关闭
                //navigator.pop();  
                //比如再次执行这条语句就是关闭TestCon页面了
              }, child: Text("关闭")),
            ],
          ),
/*        //当我们把上面的(_) =>改为 (context)=> 时
          builder:(context)=> AlertDialog(
            title: Text('Dialog Title'),
            actions: [
              TextButton(onPressed: () {
                Navigator.of(context).pop();  
//这时可以正常关闭弹窗,因为当前context是alertdialog自己的widget对应的context
//不会受上层MySafeButton 丢弃的影响

              }, child: Text("关闭")),
            ],
          ),
*/

        );
         navigator.pop();  
         //注意这里是关闭TestCon页面,flutter从context往上查找最近的navigator关闭
      },
    );
  }
}

class MyDangerousButton extends StatelessWidget {
  const MyDangerousButton({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      child: Text('Open Dialog Then Pop Dangerously'),
      onPressed: () async {
        await showDialog(
          context: context,
          builder: (_) => AlertDialog(
            title: Text('Dialog Title'),
          ),
        );

        Navigator.of(context).pop();  
//报错 Do not use BuildContexts across async gaps.
//所以我们可以提前把旧context对应的navigator也就是Navigator.of(context)存储起来,
//这样就不会出从旧的context查找navigator的问题,也就是上面mysafeBUtton中所用的解决方法
      },
    );
  }
}

Related

相关文章

同分类文章 →
2026年10月31日 flutter

`auth()->id()` 到底返回谁?Sanctum 多态令牌与双会员系统的踩坑记录

## 引子先看一段看起来很正常的代码:```php$userId = auth('sanctum')-&gt;id();if ($userId) {    $res['isLiked'] = $this-&gt;likes()        -&gt;where('user_id', $userId

2026年07月28日 flutter

Dart 3 记录(Records)和密封类(Sealed classes)

Dart 3 引入了几个极其强大的语言特性,其中最耀眼、对我们日常开发改变最大的就是 记录(Records) 和 密封类(Sealed classes),它们配合 模式匹配(Pattern Matching),让 Dart 的表现力达到了现代编程语言(如 Swift、Kotlin、Rust

2026年06月29日 flutter

flutter的 Clean Architecture架构设计

Clean Architecture(清晰架构)是一种将应用程序分层的设计模式,强调关注点分离与依赖规则,通过将业务逻辑与框架、UI、数据源解耦,提升代码的可测试性、可维护性与可扩展性。在 Flutter/Dart 环境下,Clean Architecture 通

WeChat

扫码加我微信

微信二维码