【问题标题】:Flutter load json in ListView return always empty dataListView中的Flutter加载json总是返回空数据
【发布时间】:2021-04-27 10:26:21
【问题描述】:

我正在尝试构建一个简单的应用程序来查看 json 数据。 我从 Flutter 网站上的示例开始:https://flutter.dev/docs/cookbook/networking/fetch-data

这是有效的。

现在我正在尝试从以下位置加载 cmets 列表:https://jsonplaceholder.typicode.com/comments/

当我运行应用程序时,我只看到从 CircularProgressIndicator 加载的圆圈。为什么?我无法获取数据,但我不明白为什么,你能帮帮我吗?代码如下:

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter json test',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter json test'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  Future<List<Comment>> _getComments() async {

    var data = await http.get("https://jsonplaceholder.typicode.com/comments/");
    List<Comment> comments = [];

    if(data.statusCode==200) {
      var jsonData = json.decode(data.body);

      for (var d in jsonData) {
        Comment comment = Comment(
            d["postId"],d["id"], d["name"], d["email"], d["body"]);

        comments.add(comment);
      }

      print(comments.length.toString());

      return comments;
    }
    else {
      throw Exception('Failed to load album');
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: Container(
        child: FutureBuilder(
          future: _getComments(),
          builder: (BuildContext context, AsyncSnapshot snapshot){
            if(snapshot.hasData){
              return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    title: Text( snapshot.data[index]['name']),
                    subtitle: Text(snapshot.data[index]['email']),
                    onTap: (){
                      Navigator.push(context,
                          new MaterialPageRoute(builder: (context) => DetailPage(snapshot.data[index]))
                      );
                    },
                  );
                },
              );
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {

  final Comment comment;

  DetailPage(this.comment);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(comment.name),
        )
    );
  }
}


class Comment {
  final int postId;
  final String id;
  final String name;
  final String email;
  final String body;

  Comment(this.postId, this.id, this.name, this.email, this.body);

}

你能给我一些建议吗?谢谢!

【问题讨论】:

    标签: android json flutter


    【解决方案1】:

    首先,您需要将您的 JSON 数据转换为 Map&lt;String, dynamic&gt;,然后将其解析为 List。通过查看您的code,您仅将数据转换为列表,因此Type int is not a subtype of String error occurred。此外,您还没有在 FutureBuilder 中添加错误语句,因此您必须面对阅读错误的困难,所以请检查我的答案

    您需要从您的main.dart 文件中调用此CommentPage

    class CommentPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return _homePage();
      }
    }
    
    class _homePage extends State<CommentPage> {
      Future<List<CommentModel>> getPostData() async {
        var url = "https://jsonplaceholder.typicode.com/comments";
        final responce = await http.get(url);
        final parsed = json.decode(responce.body).cast<Map<String, dynamic>>();
        return parsed.map<CommentModel>((json) {
          return CommentModel.fromJson(json);
        }).toList();
      }
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          body: Container(
            child: FutureBuilder<List<CommentModel>>(
              future: getPostData(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, int index) {
                      return ListTile(
                          title: Text(snapshot.data[index].name),
                          subtitle: Text(snapshot.data[index].email));
                    },
                  );
                } else if (snapshot.hasError) {
                  return Center(
                    child: Text(snapshot.error.toString()),
                  );
                }
                return Center(
                  child: CircularProgressIndicator(),
                );
              },
            ),
          ),
        );
      }
    }
    

    这是我的model 课程。这是我使用this 在线工具创建的。

    class CommentModel {
      CommentModel({
        this.postId,
        this.id,
        this.name,
        this.email,
        this.body,
      });
    
      int postId;
      int id;
      String name;
      String email;
      String body;
    
      factory CommentModel.fromJson(Map<String, dynamic> json) => CommentModel(
        postId: json["postId"],
        id: json["id"],
        name: json["name"],
        email: json["email"],
        body: json["body"],
      );
    
      Map<String, dynamic> toJson() => {
        "postId": postId,
        "id": id,
        "name": name,
        "email": email,
        "body": body,
      };
    }
    

    【讨论】:

      【解决方案2】:

      您返回的是 Comment 实例而不是 Map 实例,因此您应该使用点访问器。我确定如果您检查控制台,您可能会看到错误。

      ListView.builder(
        itemCount: snapshot.data.length,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text( snapshot.data[index].name), // Change here
            subtitle: Text(snapshot.data[index].email), // Change here
            onTap: () {
              Navigator.push(context,
               new MaterialPageRoute(builder: (context) => 
                  DetailPage(snapshot.data[index]))
               );
            },
          );
        }
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-18
        • 2023-02-03
        • 2020-03-08
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多