【问题标题】:Flutter: JSON data , list under listFlutter:JSON数据,列表下列表
【发布时间】:2020-10-20 00:05:52
【问题描述】:

我的 JSON 数据文件看起来像这样,您可以看到电子邮件本身就是一个列表:

[
    {
        "index": 0,
        "about": "text text text",
        "email": [
            "kjdkffsk@skfjsd.com",
            "kjdkffsk@skfjsd.com",
        ],
        "name": "sample name",
        "picture": "https://kdjfksfjsdklfs.com"
    },
    {
        "index": 1,
        "about": "text text text",
        "email": [
            "kjdkffsk@skfjsd.com",
            "kjdkffsk@skfjsd.com",
        ],
        "name": "sample name ",
        "picture": "https://kdjfksfjsdklfs.com"
    },
    {
        "index": 2,
        "about": "text text text",
        "email": [
            "kjdkffsk@skfjsd.com",
            "kjdkffsk@skfjsd.com",
        ],
        "name": "sample name",
        "picture": "https://kdjfksfjsdklfs.com"
    }
]

我的代码如下,它基本上是一个从上述 JSON 获取数据的列表视图构建器。现在,当单击列表时,它会导航到我需要显示此用户详细信息的下一页。

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

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

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

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

  final String title;

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

Future _data;

class _MyHomePageState extends State<MyHomePage> {
  Future<List<User>> _getUsers() async {
    var data =
        await DefaultAssetBundle.of(context).loadString("assets/test.json");

    var jsonData = json.decode(data);

    List<User> users = [];

    for (var u in jsonData) {
      User user =
          User(u["index"], u["about"], u["name"], u["email"], u["picture"]);

      users.add(user);
    }

    print(users.length);

    return users;
  }

  @override
  void initState() {
    super.initState();
    _data = _getUsers();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: Container(
        child: FutureBuilder(
          future: _data,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            print(snapshot.data);
            if (snapshot.data == null) {
              return Container(child: Center(child: Text("Loading...")));
            } else {
              return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    leading: CircleAvatar(
                      backgroundImage:
                          NetworkImage(snapshot.data[index].picture),
                    ),
                    title: Text(snapshot.data[index].name),
                    // subtitle: Text(snapshot.data[index].email),
                    onTap: () {
                      Navigator.push(
                          context,
                          new MaterialPageRoute(
                              builder: (context) =>
                                  DetailPage(snapshot.data[index])));
                    },
                  );
                },
              );
            }
          },
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {
  final User user;

  DetailPage(this.user);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(user.name),
      ),
      body: Container(
        child: Text(user.about),
      ),
    );
  }
}

class User {
  final int index;
  final String about;
  final String name;
  final String email;
  final String picture;

  User(this.index, this.about, this.name, this.email, this.picture);
}

我想在第二页中为名称和电子邮件创建 Listview Builder,以便在名称下列出所有电子邮件。

谁能帮助我无法生成第二页列表,尤其是电子邮件列表。

【问题讨论】:

    标签: json flutter dart flutter-listview


    【解决方案1】:

    看看这个例子,让我知道它是否适合你:

    import 'package:flutter/material.dart';
    import 'dart:async';
    import 'dart:convert';
    
    import 'package:json_parsing_example/models.dart';
    
    // To parse this JSON data, do
    //
    //     final user = userFromJson(jsonString);
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Users'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    Future _data;
    
    class _MyHomePageState extends State<MyHomePage> {
      Future<List<User>> _getUsers() async {
        var data =
            await DefaultAssetBundle.of(context).loadString("json/parse.json");
    
        return userFromJson(data);
      }
    
      @override
      void initState() {
        super.initState();
        _data = _getUsers();
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: Container(
            child: FutureBuilder<List<User>>(
              future: _data,
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                print(snapshot.data);
                if (snapshot.data == null) {
                  return Container(child: Center(child: Text("Loading...")));
                } else {
                  return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        leading: CircleAvatar(
                          backgroundImage:
                              NetworkImage(snapshot.data[index].picture),
                        ),
                        title: Text(snapshot.data[index].name),
                        // subtitle: Text(snapshot.data[index].email),
                        onTap: () {
                          Navigator.push(
                              context,
                              new MaterialPageRoute(
                                  builder: (context) =>
                                      DetailPage(snapshot.data[index])));
                        },
                      );
                    },
                  );
                }
              },
            ),
          ),
        );
      }
    }
    
    class DetailPage extends StatefulWidget {
      final User user;
    
      DetailPage(this.user);
    
      @override
      _DetailPageState createState() => _DetailPageState();
    }
    
    class _DetailPageState extends State<DetailPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.user.name),
          ),
          body: Container(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    widget.user.name,
                    style: TextStyle(fontSize: 20),
                  ),
                ),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: widget.user.email.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Card(
                        child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(widget.user.email[index]),
                    ));
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    
    

    你的模型类:

    // To parse this JSON data, do
    //
    //     final user = userFromJson(jsonString);
    
    import 'dart:convert';
    
    List<User> userFromJson(String str) => List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
    
    String userToJson(List<User> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
    
    class User {
        User({
            this.index,
            this.about,
            this.email,
            this.name,
            this.picture,
        });
    
        int index;
        String about;
        List<String> email;
        String name;
        String picture;
    
        factory User.fromJson(Map<String, dynamic> json) => User(
            index: json["index"],
            about: json["about"],
            email: List<String>.from(json["email"].map((x) => x)),
            name: json["name"],
            picture: json["picture"],
        );
    
        Map<String, dynamic> toJson() => {
            "index": index,
            "about": about,
            "email": List<dynamic>.from(email.map((x) => x)),
            "name": name,
            "picture": picture,
        };
    }
    
    

    【讨论】:

    • 它有效,感谢您。但我需要在第二页上的电子邮件上方显示用户名,而不是在应用栏中。我怎样才能做到这一点。我的意思是在运行 listview builder 时,它会首先显示名称,然后是电子邮件列表
    • 只需检查我使用列作为父级所做的更改以及顶部的名称,然后是您的列表视图,并且不要忘记添加收缩包装为 true 为 listview 因为您正在使用该列,因此 Listview 将仅根据子项占用空间。
    • 非常感谢您的支持。高度赞赏
    • 请提供更多帮助:我需要想出一个变量来加入所有这样的电子邮件:var emailall = widget.user.email.join("\n\n"); 但这不起作用。可以请帮助修复它,让我知道我把它放在哪里。我需要在第二页使用
    • 加入是什么意思?你能详细说明一下吗?
    【解决方案2】:

    首先: 您可以使用任一

    • moor/moor_flutter moor flutter_moor
    • 内置值 built_value

      映射json字符串并生成fromJson/toJson函数。

      使用 moor 的示例:
    • 首先,创建一个 moor 数据库(如果您有任何问题,我很乐意回答)。
    • 其次,这将是您应该使用的类。
    import 'dart:convert';
    import 'package:db/moordb/database.dart';
    import 'package:json_annotation/json_annotation.dart' as json;
    import 'package:moor/moor.dart';
    
    part 'user.g.dart';
    
    @DataClassName("User")
    class Users extends Table {
      IntColumn get id => integer().nullable().autoIncrement()();
    
      @JsonKey("index")
      IntColumn get index => text().nullable()();
    
      @JsonKey("about")
      TextColumn get about => text().nullable()();
    
      @JsonKey("email")
      TextColumn get emails => text().map(const EmailConverter()).nullable()();
    
      @JsonKey("name")
      TextColumn get name => text().nullable()();
    
      @JsonKey("picture")
      TextColumn get picture => text().nullable()();
    
      @override
      Set<Column> get primaryKey => {id};
    }
    
    class EmailConverter extends TypeConverter<List<String>, String> {
      const EmailConverter ();
    
      @override
      List<String> mapToDart(String fromDb) {
        if (fromDb == null) {
          return null;
        }
        List _emails = List<String>();
        (jsonDecode(fromDb)).forEach((value) {
          _emails.add(value);
        });
        return _emails;
      }
    
      @override
      String mapToSql(List<dynamic> value) {
        if (value == null) {
          return null;
        }
        return jsonEncode(value);
      }
    }
    

    第二:

    您最好通过以下方式发送用户对象:

    在您的情况下,您将对象直接传递给小部件。
    总之,很明显,用户对象中的字符串字段 email 没有被包含列表中电子邮件的解码数据填充。 (因为您使用的是类用户)。

    注意:丢失 new 关键字,因为 Dart 2 不再需要它

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多