Flutter:在 http.get 请求之后构建 ListView
Posted
技术标签:
【中文标题】Flutter:在 http.get 请求之后构建 ListView【英文标题】:Flutter: Build ListView After http.get Request 【发布时间】:2019-07-24 15:48:22 【问题描述】:我觉得这个问题不应该花 6 个多小时来解决,但我在这里经过大量搜索和玩弄代码。 基本上,当我导航到页面时,future 会自动从 _getData() 发送 http.get 请求。我正在获取数据并构建一个 ListView 就好了,问题是我希望 ListView 仅在从 TextField 提交搜索词之后构建。任何帮助将不胜感激!
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);
【问题讨论】:
【参考方案1】:为了回答您的问题,我简化/修改了一些代码,因此不需要网络调用。
注意布尔变量“show_results”的声明。这是你想做的事情的关键。确保记下变量的所有用法。
在两个 setState () 构造中,它首先关闭所需列表的可见性/存在性,然后在执行搜索后打开所需列表的可见性/存在性。
此代码已经过测试,如图所示。
希望这会有所帮助。
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);
【讨论】:
顺便说一句,它应该与您的http调用基本相同,只是我无法访问您的网站搜索。 谢谢布拉德福德先生!我喜欢你在那里所做的,这绝对有帮助。现在,行为符合预期,但我对学习状态行为以及如何操作它是新手。也就是说,当页面被路由到时,HTTP 调用仍然会立即调用,而不是等待搜索词被提交。然后它在提交时也会调用 x4 ,并且变量在 _url 内没有变化,即无论输入什么字符串,总是返回默认搜索。将在此工作并在/如果我找到解决方案时发布。 ~再次感谢!以上是关于Flutter:在 http.get 请求之后构建 ListView的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:为 Http GET 请求发送 JSON 正文
在 Flutter 中每 1 分钟发出一次定时 http.get 请求的最简单方法是啥?
在 Flutter Web 应用程序中对 http 和 https API 服务器的 http GET 请求发生异常