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