我正在使用 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'),因此快照在我的 ListView 小部件中作为 null 传递。
这是 _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 返回此 Snapshot AsyncSnapshot>(ConnectionState.waiting, null, null)