如何等待使用FutureBuilder从屏幕或对话框返回数据?

时间:2020-08-26 05:11:58

标签: flutter

我希望FutureBuilder等待用户在路线或对话框(以下示例)中进行选择,然后将该数据返回给构建器。但是,对话框永远不会出现。

我如何等待使用FutureBuilder从屏幕或对话框返回数据?

DartPad

import 'package:flutter/material.dart';

void main() => runApp(HomeScreen());

class HomeScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder(
            future: launch(context),
            builder: (context, snapshot) {
              // use result from screen or dialog in snapshot.data
              return Center(child: Text(snapshot.data));
            }),
      ),
    );
  }

  Future launch(BuildContext context) async {
    return await showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          actions: <Widget>[
            FlatButton(
              child: Text('Send Data'),
              onPressed: () {
                // return some data
                Navigator.pop(context, 'Some data!');
              },
            ),
          ],
          content: Container(child: Text('')),
        );
      },
    );
  }
}

2 个答案:

答案 0 :(得分:2)

您可以在下面复制粘贴运行完整代码
步骤1:您需要使用addPostFrameCallback
步骤2:将MaterialApp移到上一级
步骤3:检查ConnectionState
代码段

@override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      setState(() {
        _future = launch(context);
      });
    });

    super.initState();
  }

Future<String> launch(BuildContext context) async {
    var result = await showDialog(
     ...

    print("result $result");
    return Future.value(result);
  }

工作演示dartpad link

enter image description here

完整代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  Future<String> _future;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      setState(() {
        _future = launch(context);
      });
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: FutureBuilder(
            future: _future,
            builder: (context, AsyncSnapshot<String> snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                  return Text('none');
                case ConnectionState.waiting:
                  return Center(child: CircularProgressIndicator());
                case ConnectionState.active:
                  return Text('');
                case ConnectionState.done:
                  if (snapshot.hasError) {
                    return Text(
                      '${snapshot.error}',
                      style: TextStyle(color: Colors.red),
                    );
                  } else {
                    return Center(child: Text("his this is ${snapshot.data}"));
                  }
              }
            }),
      ),
    );
  }

  Future<String> launch(BuildContext context) async {
    var result = await showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          actions: <Widget>[
            FlatButton(
              child: Text('Send Data'),
              onPressed: () {
                // return some data
                Navigator.pop(context, 'Some data!');
              },
            ),
          ],
          content: Container(child: Text('')),
        );
      },
    );

    print("result $result");
    return Future.value(result);
  }
}

答案 1 :(得分:1)

感谢您使用将来的Completer进行还原,以从Dialogue中获取数据

创建一个Completer实例

var dialogueFuture = Completer();

将完成者的未来提供给Future builder

FutureBuilder{
future : dialogueFuture.future,
...
}

在显示对话功能中,像这样完成Future

var theData = await showDialogue(...)
dialogFuture.complete(theData);

请参阅飞镖here