首页 > 解决方案 > 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();
                    },
                  ),
                ),
              ],
            ),
          )
      );
  }

标签: jsonhttpflutterdartget

解决方案


伙计,我随心所欲地重写你的代码

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'])
        ],
      ),
    );
  }
}

推荐阅读