我想呈现一个需要HTTP调用来收集一些数据的小部件。
获得以下代码(简化)
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'async demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var asyncWidget;
@override
initState() {
super.initState();
loadData().then((result) {
print(result);
setState(() {
asyncWidget = result;
});
});
}
loadData() async {
var widget = new AsyncWidget();
return widget.build();
}
@override
Widget build(BuildContext context) {
if(asyncWidget == null) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Loading..."),
),
);
} else {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: this.asyncWidget,
),
);
}
}
}
class MyRenderer {
MyRenderer();
Widget render (List data) {
List<Widget> renderedWidgets = new List<Widget>();
data.forEach((element) {
renderedWidgets.add(new ListTile(
title: new Text("one element"),
subtitle: new Text(element.toString()),
));
});
var lv = new ListView(
children: renderedWidgets,
);
return lv;
}
}
class MyCollector {
Future gather() async {
var response = await // do the http request here;
return response.body;
}
}
class AsyncWidget {
MyCollector collector;
MyRenderer renderer;
AsyncWidget() {
this.collector = new MyCollector();
this.renderer = new MyRenderer();
}
Widget build() {
var data = this.collector.gather();
data.then((response) {
var responseObject = JSON.decode(response);
print(response);
return this.renderer.render(responseObject);
});
data.catchError((error) {
return new Text("Oups");
});
}
}
我的代码是这样工作的:使用异步数据的小部件需要一个收集器(它进行http调用)和一个呈现器(它将呈现带有http数据的小部件)。2我在initState()上创建了这个小部件的一个示例,然后进行异步调用。
我发现一些文档说我们应该使用setState()方法用新数据更新小部件,但这对我不起作用。
但是,当我放置一些日志时,我看到HTTP调用完成,setState()方法被调用,但小部件没有更新。
2条答案
按热度按时间ckx4rj1h1#
最好的方法是使用FutureBuilder。
来自FutureBuilder文档:
另一件事是,您在www.example.com方法之外构建小部件State.build,并保存小部件本身,这是一个反模式,您应该每次都在build方法中构建小部件。
您可以在没有FutureBuilder的情况下使用它,但是您应该保存http调用的结果(经过适当的处理),然后在构建函数中使用这些数据。
请注意,使用FutureBuilder是一种更好的方法,我只是提供这些内容供您学习。
46scxncf2#
完整示例
异步调用后rander小工具的最佳方式是使用**
FutureBuilder()
**在future builder中,它调用future函数以等待结果,一旦产生结果,它就调用我们构建小部件的builder函数。
异步快照有3种状态: