json - Flutter:在第二页中加载 json 数据 Flutter 类超时而没有错误
问题描述
我从口袋妖怪列表的口袋妖怪 API 生成了一个 listView,然后我有 onTap 事件来触发一个新的页面/类,我将 API 中的名称和 URL 传递给新的 secondPage 类/屏幕。
我需要在这个新页面中发出第二个请求,因为 API Url 需要更改以获取特定详细信息,但我的请求似乎超时..
这是我的代码:如果加载到新项目中,第一个屏幕应该可以正常工作,将一堆 Pokemon 及其 API 特定 URL 加载到 listView 中。
我可以成功地将名称和 URL 传递到第二个屏幕,因为它们确实出现在 Appbar 中。
但是,在加载新的 json 数据时,它似乎超时而没有任何错误。
有人对试图站稳脚跟的新手有什么建议吗?
import 'dart:async';
import 'dart:convert';
import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
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(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController editingController = TextEditingController();
String url = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
List data;
Future<String> makeRequest() async {
var response = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var extractData = json.decode(response.body);
data = extractData["results"];
});
}
@override
void initState() {
this.makeRequest();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Pokemon List'),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: new TextField(
onChanged: (value) {
},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
contentPadding: const EdgeInsets.all(10.0),
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(6.0))
),
),
),
),
Expanded(
child: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(StringUtils.capitalize(data[i]["name"])),
subtitle: new Text(data[i]["url"]),
// leading: new CircleAvatar(
// backgroundImage:
// new NetworkImage(data[i]["picture"]["thumbnail"]),
// ),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondPage(data[i])
)
);
},
);
}
),
),
],
),
),
);
}
}
// Class for getting Specific Details on SecondPage
class Post {
final String name;
final int weight;
Post({this.name, this.weight});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
name: json['name'],
weight: json['weight'],
);
}
}
// New Request for Specific Details
class SecondPage extends StatelessWidget {
SecondPage(this.data);
final data;
Future<Post> fetchPost() async {
final response =
await http.get('https://pokeapi.co/api/v2/pokemon/' + data["name"]);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
Future<Post> post;
@override
void initState() {
fetchPost();
post = fetchPost();
}
@override
Widget build(BuildContext context) =>
new Scaffold(
appBar: new AppBar(
title: new Text(data["name"] + ' - ' + data["url"])),
body: new Center(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.all(30.0),
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
Text(snapshot.data.name);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
],
),
)
);
}
解决方案
伙计,我随心所欲地重写你的代码
import 'dart:async';
import 'dart:convert';
//import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController editingController = TextEditingController();
String url = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
List data;
Future<String> makeRequest() async {
var response = await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var extractData = json.decode(response.body);
data = extractData["results"];
});
}
@override
void initState() {
super.initState();
makeRequest();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pokemon List'),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: TextField(
onChanged: (value) {},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
contentPadding: const EdgeInsets.all(10.0),
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(6.0))),
),
),
),
Expanded(
child: ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return ListTile(
title: Text(data[i]["name"].toString().toUpperCase()),
subtitle: Text(data[i]["url"]),
// leading: CircleAvatar(
// backgroundImage:
// NetworkImage(data[i]["picture"]["thumbnail"]),
// ),
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (BuildContext context) => SecondPage(data[i])));
},
);
}),
),
],
),
),
);
}
}
class SecondPage extends StatefulWidget {
Map data;
SecondPage(this.data);
_SecondState createState() => _SecondState();
}
class _SecondState extends State<SecondPage> {
@override
void initState() {
super.initState();
_fetchPost();
}
Map post;
bool isLoad = true;
_fetchPost() async {
setState(() {
isLoad = true;
});
var url = widget.data["url"];
debugPrint(url);
final response = await http.get(url);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
post = json.decode(response.body.toString());
setState(() {
isLoad = false;
});
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.data["name"] + ' - ' + widget.data["url"])),
body: _buildPokemon(context),
);
}
Widget _buildPokemon(BuildContext context) {
if (isLoad) return Center(child: CircularProgressIndicator());
return Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(post['name']),
Text(post['weight'].toString()),
Text(post['height'].toString()),
Image.network(post['sprites']['front_default'])
],
),
);
}
}
推荐阅读
- r - 为 rollapply 窗口应用循环
- mysql - 为什么没有聚合函数的选择列需要成为 MySQL 中 Group by 子句的一部分?
- android - RxJava 如何在链中的不同点以不同方式处理错误
- java - NotSerializableException:java.io.FileInputStream
- linux - GIT 上传 - Linux 用户名显示而不是 git 用户名
- javascript - 自动滚动 fullcalendar V5(resourceTimelineWeek View) 到当前日期和时间
- ios - 如何更改 SwiftUI 和 iOS 14 中的单元格背景颜色?
- python - 列出 Apache Airflow 上的索引外
- vhdl - 触发非常短的脉冲 - VHDL
- xaml - UWP:当按下相应的单选按钮时,如何使 ContentPresenter 的 FontWeight 保持不变?