[英]Flutter: Build ListView After http.get Request
I feel like this problem shouldn't take 6+ hours to figure out yet here I am after much searching and playing around with code. 我觉得这个问题应该花6个多小时才能弄清楚,但在这里我经过大量的搜索和使用代码。 Basically, when I nav to the page, the future automatically sends the http.get request from _getData(). 基本上,当我浏览该页面时,将来会自动从_getData()发送http.get请求。 I'm getting the data and building a ListView just fine, the problem is that I want the ListView to only build AFTER a search term has been submitted from the TextField. 我正在获取数据并构建一个ListView很好,问题是我希望ListView仅在从TextField提交搜索词后才构建。 Any help would be greatly appreciated! 任何帮助将不胜感激!
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
class FutureBuilderTestPage extends StatefulWidget {
@override
BuilderTestPageState createState() => BuilderTestPageState();
}
class BuilderTestPageState extends State {
static String _searchTerm = "";
String _url = "https://api.nal.usda.gov/ndb/search/?format=json&q=$_searchTerm&sort=n&max=20&offset=0&api_key=OMITTEDforThisPost";
@override
Widget build(BuildContext context) {
var _futureBuilder = new FutureBuilder(
future: _getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return Text('Awaiting result...');
case ConnectionState.done:
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
// return Text('Result: ${snapshot.data}');
return createMyListView(context, snapshot);
}
return null; // unreachable
});
return new Scaffold(
appBar: new AppBar(
title: Text("Appbar"),
),
body: Column(
children: <Widget>[
Text("Search for food..."),
TextField(
decoration: InputDecoration(hintText: 'Search here'),
onSubmitted: (String valueIn) {
_searchTerm = valueIn;
},
),
Text("Results for... " + _searchTerm),
Divider(height: 4.0),
Expanded(child: _futureBuilder),
],
));
}
Future<List<dynamic>> _getData() async {
http.Response response = await http.get(_url,
headers: {"Accept": "Application/json"});
final data = jsonDecode(response.body) as Map;
final mapOfList = data['list'] as Map;
final listOfItem = mapOfList['item'] as List<dynamic>;
print(listOfItem.toString());
var values = new List<dynamic>();
for (var e in listOfItem) {
values.add(e);
}
return values;
}
Widget createMyListView(BuildContext context, AsyncSnapshot snapshot) {
List<dynamic> values = snapshot.data;
return new ListView.builder(
itemCount: values.length,
itemBuilder: (BuildContext context, int index) {
return new Column(
children: <Widget>[
new ListTile(
title: new Text(values[index]['name']),
)
],
);
},
);
}
}
class FoodObjectFromJson {
final int offset;
final String group;
final String name;
final int ndbno;
final String ds;
final String manu;
FoodObjectFromJson(
this.offset, this.group, this.name, this.ndbno, this.ds, this.manu);
}
To answer your question I simplified/modified the code some so a web call is not required. 为了回答您的问题,我对代码进行了简化/修改,因此不需要进行网络调用。
Note the declaration of bool variable "show_results". 注意布尔变量“ show_results”的声明。 It is key to what you desire to do. 这是您想要做什么的关键。 Make sure you note all usages of the variable. 确保记下该变量的所有用法。
Inside the two setState () constructs it first turns off the visibility/existence of your desired list and then after your search has been performed it turns on the visibility/existence of your desired list. 在两个setState()构造内部,它首先关闭所需列表的可见性/存在性,然后在执行搜索之后,打开所需列表的可见性/存在性。
This code has been tested and works as shown. 该代码已经过测试,工作原理如下所示。
Hope this helps. 希望这可以帮助。
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
class zFutureBuilderTestPage extends StatefulWidget {
@override
zBuilderTestPageState createState() => zBuilderTestPageState();
}
class zBuilderTestPageState extends State {
static String _searchTerm = "";
bool show_results=false;
String _url = "https://www.awebsite.com/search.php";
@override
Widget build(BuildContext context) {
var _futureBuilder = new FutureBuilder(
future: _getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return Text('Awaiting result...');
case ConnectionState.done:
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
// return Text('Result: ${snapshot.data}');
return createMyListView(context, snapshot);
}
return null; // unreachable
});
return new Scaffold(
appBar: new AppBar(
title: Text("Appbar"),
),
body: Column(
children: <Widget>[
Text("Search for food..."),
TextField(
decoration: InputDecoration(hintText: 'Search here'),
onSubmitted: (String valueIn) => search(valueIn),
),
Text("Results for... " + _searchTerm),
Divider(height: 4.0),
show_results == false ? new Container ( width: 0, height: 0 ) : Expanded(child: _futureBuilder),
],
));
}
Future <List<dynamic>> search ( String valueIn ) async {
print (valueIn);
setState(() {
show_results=false;
});
List<dynamic> l = await _getData();
setState(() {
show_results=true;
});
return ( l );
}
Future<List<dynamic>> _getData() async {
List<FoodObjectFromJson> values=new List();
FoodObjectFromJson H =new FoodObjectFromJson(5,"Orange");
values.add( H );
FoodObjectFromJson H2 =new FoodObjectFromJson(8,"Apple");
values.add( H2 );
FoodObjectFromJson H3 =new FoodObjectFromJson(22,"Pear");
values.add( H3 );
return values;
}
Widget createMyListView(BuildContext context, AsyncSnapshot snapshot) {
List<dynamic> values = snapshot.data;
return new ListView.builder(
itemCount: values.length,
itemBuilder: (BuildContext context, int index) {
return new Column(
children: <Widget>[
new ListTile(
title: new Text(values[index].fruit_handle),
)
],
);
},
);
}
}
class FoodObjectFromJson {
final int fruit_id;
final String fruit_handle;
FoodObjectFromJson(
this.fruit_id, this.fruit_handle);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.