Flutter 如何仅在异步方法完成后调用方法

Flutter 如何仅在异步方法完成后调用方法,flutter,asynchronous,Flutter,Asynchronous,背景 我有一个包含异步方法getData()的PriceScreen类。此PriceScreen类使用从getData()返回的GraphValue中的数据调用类图 问题 调用GraphGraph(closingTimesAndPrices:graphValues) 在getData完成之前运行,导致在上面的调用中传递的GraphValue变为Null。如何更改代码,使对Graph的调用等待调用,直到getData完成处理 注意:我添加了“我通常在then()中配对下一个wait方法。类似于:

背景 我有一个包含异步方法getData()的PriceScreen类。此PriceScreen类使用从getData()返回的GraphValue中的数据调用类图

问题 调用Graph
Graph(closingTimesAndPrices:graphValues)

在getData完成之前运行,导致在上面的调用中传递的GraphValue变为Null。如何更改代码,使对Graph的调用等待调用,直到getData完成处理


注意:我添加了“我通常在then()中配对下一个wait方法。类似于:

Map coinData = await CoinData().getCoinData(selectedCurrency);
await GraphData().getGraphData(
  selectedCurrency: selectedCurrency,
  selectedGraphType: selectedGraphType).then((graphData ) {
  setState(() {
    coinValues = coinData;
    graphValues = graphData;
  });
});

最好的做法是不要延迟执行build方法,您应该做的是在获取GraphValue时显示进度条

现在,您可以通过多种方式实现这一点。使用bloc、streambuilder等是一些最好的方法。但对于最简单的解决方案,您可以使用以下代码:

@override
Widget build(BuildContext context) {
      if(grapheValues.isEmpty) {
        return Center(
          child: CircularProgressIndicator(),
        );
      } else {
          Graph(closingTimesAndPrices: graphValues), <<<-------------------
      }
}
@覆盖
小部件构建(构建上下文){
if(grapherValues.isEmpty){
返回中心(
子对象:CircularProgressIndicator(),
);
}否则{

Graph(closingTimesAndPrices:graphValues),感谢您回答我的问题并推荐使用StreamBuilder。我使用StreamBuilder解决了我原来帖子中的问题

我需要在代码中添加三个部分:

 1) Future futureData;

 2) futureData = getData();

 3) FutureBuilder(
                future: futureData,
                builder: (context, snapshot) {
                  if (graphValues.isEmpty) {
                    return new Container();
                  } else
                  return Graph(closingTimesAndPrices: graphValues);
                })
我在FutureBuilder中使用futureData作为
future:
的值,以表示我正在等待futureData(getData();)完全完成,然后才返回任何内容。在我的原始帖子中,我提到GraphValue在getData()完成处理之前返回null。为了纠正这一问题,我检查GraphValue是否为空

                      if (graphValues.isEmpty) {
                        return new Container();
                      } else
                      return Graph(closingTimesAndPrices: graphValues);
如果graphValues为空,我将返回新容器();该容器不会向用户显示任何内容。如果graphValues不为空,我将使用
Graph(closingTimesAndPrices:graphValues);
,返回对Graph的调用。有些人可能建议我包括一个CircularProgressIndicator,而不是
new Container()当graphValues为空,但我已经有了一个循环进程指示器,如
body:ModalProgressHUD(

inAsyncCall: isWaiting,
        progressIndicator: CircularProgressIndicator(
          backgroundColor: Colors.orange, 
以下是一些帮助我学习StreamBuilder并帮助我解决问题的资源:

我的代码中添加的内容在下面用三个星号(***)表示

完整代码:

class PriceScreen extends StatefulWidget {
  @override
  PriceScreenState createState() => PriceScreenState();
}

class PriceScreenState extends State < PriceScreen > {
  String selectedCurrency = 'USD';
  String selectedGraphType = "1M";
  Map < String,String > coinValues = {};
  Map < String,double > graphValues = {};
 ***Future futureData;

  bool isWaiting = false;

  getData() async {
    isWaiting = true;
    try {
      Map coinData = await CoinData().getCoinData(selectedCurrency);
      Map graphData = await GraphData().getGraphData( 
        selectedCurrency: selectedCurrency,
        selectedGraphType: selectedGraphType);
      isWaiting = false;
      setState(() {
        coinValues = coinData;
        graphValues = graphData; 
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  void initState() {
    super.initState();
 ***futureData = getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Crypto Watcher'),
      ),
      body: ModalProgressHUD(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
       ***child: FutureBuilder(
                future: futureData,
                builder: (context, snapshot) {
                  if (graphValues.isEmpty) {
                    return new Container();
                  } else
                    print(graphValues);
                  return Graph(closingTimesAndPrices: graphValues);
                }), 
          ),
        inAsyncCall: isWaiting,
        progressIndicator: CircularProgressIndicator(
          backgroundColor: Colors.orange,
        ),
      ),
    );
  }
}
class PriceScreen扩展了StatefulWidget{
@凌驾
PriceScreenState createState()=>PriceScreenState();
}
类PriceScreenState扩展状态{
字符串selectedCurrency='USD';
字符串selectedGraphType=“1M”;
MapcoinValues={};
MapgraphValues={};
***未来数据;
bool isWaiting=false;
getData()异步{
isWaiting=true;
试一试{
Map coinData=wait coinData().getCoinData(selectedCurrency);
Map graphData=等待graphData()。getGraphData(
selectedCurrency:selectedCurrency,
selectedGraphType:selectedGraphType);
isWaiting=false;
设置状态(){
coinValues=coinData;
GraphValue=graphData;
});
}捕获(e){
印刷品(e);
}
}
@凌驾
void initState(){
super.initState();
***futureData=getData();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“加密观察者”),
),
正文:ModalProgressHUD(
子:列(
mainAxisAlignment:mainAxisAlignment.spaceBetween,
crossAxisAlignment:crossAxisAlignment.stretch,
***孩子:未来建设者(
未来:未来数据,
生成器:(上下文,快照){
if(graphValues.isEmpty){
返回新容器();
}否则
打印(图形值);
返回图(closingTimesAndPrices:GraphValue);
}), 
),
inAsyncCall:我在等你,
进程指示器:循环进程指示器(
背景颜色:Colors.orange,
),
),
);
}
}
class PriceScreen extends StatefulWidget {
  @override
  PriceScreenState createState() => PriceScreenState();
}

class PriceScreenState extends State < PriceScreen > {
  String selectedCurrency = 'USD';
  String selectedGraphType = "1M";
  Map < String,String > coinValues = {};
  Map < String,double > graphValues = {};
 ***Future futureData;

  bool isWaiting = false;

  getData() async {
    isWaiting = true;
    try {
      Map coinData = await CoinData().getCoinData(selectedCurrency);
      Map graphData = await GraphData().getGraphData( 
        selectedCurrency: selectedCurrency,
        selectedGraphType: selectedGraphType);
      isWaiting = false;
      setState(() {
        coinValues = coinData;
        graphValues = graphData; 
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  void initState() {
    super.initState();
 ***futureData = getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Crypto Watcher'),
      ),
      body: ModalProgressHUD(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
       ***child: FutureBuilder(
                future: futureData,
                builder: (context, snapshot) {
                  if (graphValues.isEmpty) {
                    return new Container();
                  } else
                    print(graphValues);
                  return Graph(closingTimesAndPrices: graphValues);
                }), 
          ),
        inAsyncCall: isWaiting,
        progressIndicator: CircularProgressIndicator(
          backgroundColor: Colors.orange,
        ),
      ),
    );
  }
}