Flutter中没有上下文的AlertDialog

时间:2019-05-23 18:05:29

标签: dart flutter dialog

我想在http获取失败时显示AlertDialog。函数showDialog(https://api.flutter.dev/flutter/material/showDialog.html)具有参数“ @required BuildContext context”,但是我想从我的异步函数getNews()调用AlertDialog,该函数没有上下文值。

与Java类似,在没有所有者的情况下,我使用null进行对话时,我尝试将上下文值设置为null,但不接受。

这是我的代码:

  Future<dynamic> getNews() async {
    dynamic retVal;
    try {
      var response = await http.get(url));
      if (response.statusCode == HttpStatus.ok) {
        retVal = jsonDecode(response.body);
      }
    } catch (e) {
      alertDlg(?????????, 'Error', e.toString());
  }
    return
    retVal;
  }

  static Future<void> alertDlg(context, String titolo, String messaggio) async {
    return showDialog<void>(
        context: context,
        barrierDismissible: false, // user must tap button!
        builder: (BuildContext context) {
        return AlertDialog(
              title: Text(titolo),
        ...
    );
  }

4 个答案:

答案 0 :(得分:21)

没有第三方库或存储BuildContext的解决方案:

final navigatorKey = GlobalKey<NavigatorState>();

void main() => runApp(
  MaterialApp(
    home: HomePage(),
    navigatorKey: navigatorKey, // Setting a global key for navigator
  ),
);

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: SafeArea(
        child: Center(
          child: Text('test')
        )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: showMyDialog, // Calling the function without providing it BuildContext
      ),
    );
  }
}

void showMyDialog() {
  showDialog(
    context: navigatorKey.currentContext,
    builder: (context) => Center(
      child: Material(
        color: Colors.transparent,
        child: Text('Hello'),
      ),
    )
  );
}

在为导航器(navigatorKey类的MaterialApp参数)设置了全局键之后,可以从代码的任何部分访问其当前状态。我们可以将其上下文传递给showDialog函数。确保在构建第一帧之前不要使用它,否则状态将为null。

基本上,对话框只是MaterialPageRouteCupertinoPageRoute之类的另一种路由-它们都从ModalRoute类派生而其实例被推入NavigatorState中。仅需要上下文即可获取当前导航器的状态。如果我们具有全局导航键,则可以在没有上下文的情况下推送新路线:

navigatorKey.currentState.push(route)

不幸的是,_DialogRoute函数中使用的showDialog类(... \ flutter \ lib \ src \ widgets \ routes.dart)是私有的且不可访问,但是您要创建自己的对话框路由类,并且将其推入导航器的堆栈中。

更新Navigator.of方法已更新,不再需要传递子树上下文。

答案 1 :(得分:9)

接受的答案是错误的。

对话框仅需要上下文即可通过继承的navigationState访问它。 您可以创建自己的修改对话框,也可以使用此lib来完成此操作。

https://pub.dev/packages/get

通过它,您可以从代码的任何位置打开对话框而无需上下文:

Get.dialog(SimpleDialog());

答案 2 :(得分:1)

如果使用await,则在您进行getNews调用时捕获异常,否则使用Future的catchError属性。

答案 3 :(得分:1)

因此,您需要一个BuildContext来创建一个对话框,但是您无权访问它。这是一个常见的问题,您可以参考this StackOverflow question来找到解决问题的一种方法(创建一个静态对话框并在需要的地方显示它)。

您可能考虑的另一种方法是在创建异步方法或对象作为参数时传递上下文。确保完成后将其为空。

或者您可以创建一个在特定条件下变为“ true”的标志(布尔值),并且在build()方法之一中,您始终会检查该标志,如果它是“ true”,请执行以下操作(显示一个对话框)。