我正在使用API调用来获取数据并显示在ListView中。
这是将来的构建器类:
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
}
},
);
}
}
问题是,甚至在_getProjects()返回结果之前,也会调用debugPrint('Builder'),因此快照在null中传递为ListView窗口小部件。
这是_getProjects()类:
Future<List<Project>> _getProjects() async {
List<Project> projects = [];
String getProjects = "https://api.myjson.com/bins/1g3xpe";
var response = await http.get(getProjects);
Iterable list = json.decode(response.body);
projects = list.map((model) => Project.fromJson(model)).toList();
debugPrint('Size ' + projects.length.toString());
return projects;
}
这是完整的代码:
class Projects extends StatefulWidget {
@override
ProjectState createState() => new ProjectState();
}
class ProjectState extends State {
Future<List<Project>> _getProjects() async {
List<Project> projects = [];
String getProjects = "https://api.myjson.com/bins/1g3xpe";
var response = await http.get(getProjects);
Iterable list = json.decode(response.body);
projects = list.map((model) => Project.fromJson(model)).toList();
debugPrint('Size ' + projects.length.toString());
return projects;
}
@override
Widget build(BuildContext context) {
return Scaffold(
primary: true,
appBar: EmptyAppBar(),
body: Column(
children: <Widget>[
headerWidget(),
futureBuilder()
],
),
);
}
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
}
},
);
}
}
Widget headerWidget() {
return Container(
padding: EdgeInsets.all(16.0),
color: Colors.blueAccent,
child: Container(
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)),
side: BorderSide(color: Colors.white))),
child: Row(
children: <Widget>[
Padding(padding: EdgeInsets.only(left: 12)),
Icon(Icons.arrow_back, color: Colors.black54),
Padding(padding: EdgeInsets.only(left: 12)),
Flexible(
fit: FlexFit.loose,
child: searchBar(),
),
Icon(
Icons.search,
color: Colors.black54,
),
Padding(padding: EdgeInsets.only(right: 12)),
],
)),
);
}
Widget searchBar() {
return Container(
height: 52,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 12, right: 12),
child: TextField(
decoration: new InputDecoration.collapsed(
border: InputBorder.none,
filled: false,
hasFloatingPlaceholder: false,
hintText: 'Search here',
hintStyle: TextStyle(color: Colors.black54),
),
),
);
}
Widget listWidget(AsyncSnapshot<List<Project>> snapshot) {
return Scaffold(
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
listItem(snapshot.data[index]);
},
itemCount: snapshot.data.length));
}
Widget listItem(Project project) {
return Card(
elevation: 6.0,
child: Column(
children: <Widget>[Text('Project ID'), Text('Project Name')],
),
);
}
class EmptyAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
return Container();
}
@override
Size get preferredSize => Size(0.0, 0.0);
}
更新: 我对FutureBuilder进行了一些更改:
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.done:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
break;
default:
debugPrint("Snapshot " + snapshot.toString());
}
},
);
}
我现在收到此错误:
I/flutter ( 4054): _FutureBuilderState<List<Project>>#67dc4):
I/flutter ( 4054): A build function returned null.
I/flutter ( 4054): The offending widget is: FutureBuilder<List<Project>>
I/flutter ( 4054): Build functions must never return null. To return an empty space that causes the building widget to
I/flutter ( 4054): fill available room, return "new Container()". To return an empty space that takes as little room as
I/flutter ( 4054): possible, return "new Container(width: 0.0, height: 0.0)".
默认情况下,SnapShot返回此快照AsyncSnapshot>(ConnectionState.waiting,null,null)
答案 0 :(得分:1)
I / flutter(4054):构建函数返回null。
无论什么情况,您始终需要从构建器返回小部件:
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.done:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
break;
default:
debugPrint("Snapshot " + snapshot.toString());
return Container() // also check your listWidget(snapshot) as it may return null.
}
},
);
}
问题是,甚至在调用debugPrint('Builder')之前 _getProjects()返回结果,因此快照在我的ListView窗口小部件中作为null传递。
这是正常现象,例如,如果您有一个漫长的任务(一个请求或一些非常长的计算),则需要显示负载,直到将来“完成”为止。另外,将要执行的内容置于“未来”,这意味着您可以“稍后”执行它,否则,您需要使用 await 。
答案 1 :(得分:0)
您需要检查AsyncSnapshot(快照)是否返回任何数据。
添加一个PRIM
语句,如下所示:
if