将本地JSON加载到ListView.builder中

时间:2018-03-14 12:48:11

标签: json listview dart flutter

尝试使用本地json中的数据创建ListView.builder时收到以下异常。

[错误:topaz / lib / tonic / logging / dart_error.cc(16)]未处理的异常: 类型'List'不是类型为cast的类型'Map'的子类型   列表来自dart:core   地图来自dart:core

请有人帮助我吗?

Future<Stream<Produto>> getProdutosFromAsset() async {
  return new Stream.fromFuture(rootBundle.loadString('assets/produtos.json'))
      .transform(json.decoder)
      .expand((jsonBody) => (jsonBody as Map)['results'])
      .map((jsonPlace) => new Produto.fromJson(jsonPlace));
}

class Despensa extends StatefulWidget {
  @override
  DespensaState createState() => new DespensaState();
}

class DespensaState extends State<Despensa> {
  var produtoList = <Produto>[];

  dataJson() async {
    final stream = await getProdutosFromAsset();
    stream.listen((place) => setState(() => produtoList.add(place)));
    produtoList.forEach((f) => print(f));
  }

  @override
  initState() {
    super.initState();
    dataJson();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Row(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            new Row(children: [
              new Icon(Icons.kitchen),
              new Text(' Despensa'),
            ]),
            new Expanded(
              child: new Icon(Icons.search),
            )
          ],
        ),
      ),
      body: new ListView.builder(
        itemBuilder: (BuildContext context, int index) =>
            new ProdutoItem(produtoList[index]),
        itemCount: produtoList.length,
      ),
    );
  }
}

produtos.json

[
    {
        "prodcd": 1,
        "proditem": false,
        "prodtitle": "Bebidas",
        "prodcont": 0,
        "prodicon": "graphics/bebidas.png",
        "proddesde": "13/03/2018",
        "prodchildren": [
            {
                "prodcd": 101,
                "proditem": false,
                "prodtitle": "Aguas",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": [
                    {
                        "prodcd": 1001,
                        "proditem": false,
                        "prodtitle": "Agua Tonica",
                        "prodcont": 0,
                        "prodicon": "",
                        "proddesde": "13/03/2018",
                        "prodchildren": []
                    },
                    {
                        "prodcd": 1002,
                        "proditem": false,
                        "prodtitle": "Agua Mineral",
                        "prodcont": 0,
                        "prodicon": "",
                        "proddesde": "13/03/2018",
                        "prodchildren": []
                    }
                ]
            },
            {
                "prodcd": 102,
                "proditem": false,
                "prodtitle": "Energeticos",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 103,
                "proditem": false,
                "prodtitle": "Chas",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 104,
                "proditem": true,
                "prodtitle": "Sucos",
                "prodcont": 1,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 105,
                "proditem": false,
                "prodtitle": "Refrescos",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 106,
                "proditem": true,
                "prodtitle": "Refrigerantes",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 107,
                "proditem": false,
                "prodtitle": "Cervejas",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 108,
                "proditem": false,
                "prodtitle": "Destilados",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 109,
                "proditem": false,
                "prodtitle": "Whisky",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            },
            {
                "prodcd": 110,
                "proditem": false,
                "prodtitle": "Vinhos e Espumantes",
                "prodcont": 0,
                "prodicon": "",
                "proddesde": "13/03/2018",
                "prodchildren": []
            }
        ]
    },
    {
        "prodcd": 2,
        "proditem": false,
        "prodtitle": "Carnes e Aves",
        "prodcont": 0,
        "prodicon": "graphics/carnes_e_aves.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 3,
        "proditem": false,
        "prodtitle": "Cereais e Farinhas",
        "prodcont": 0,
        "prodicon": "graphics/cereais.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 4,
        "proditem": false,
        "prodtitle": "Congelados",
        "prodcont": 0,
        "prodicon": "graphics/congelados.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 5,
        "proditem": false,
        "prodtitle": "Enlatados",
        "prodcont": 0,
        "prodicon": "graphics/enlatados.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 6,
        "proditem": false,
        "prodtitle": "Frios e Laticínios",
        "prodcont": 0,
        "prodicon": "graphics/frios_laticinios.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 7,
        "proditem": false,
        "prodtitle": "Higiene e Beleza",
        "prodcont": 0,
        "prodicon": "graphics/higiene.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 8,
        "proditem": false,
        "prodtitle": "Hortifruti",
        "prodcont": 0,
        "prodicon": "graphics/hortifruti.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 9,
        "proditem": false,
        "prodtitle": "Limpeza",
        "prodcont": 0,
        "prodicon": "graphics/limpeza.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 10,
        "proditem": false,
        "prodtitle": "Massas e biscoitos",
        "prodcont": 0,
        "prodicon": "graphics/massas.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 11,
        "proditem": false,
        "prodtitle": "Mercearia",
        "prodcont": 0,
        "prodicon": "graphics/mercearia.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 12,
        "proditem": false,
        "prodtitle": "Padaria",
        "prodcont": 0,
        "prodicon": "graphics/padaria.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 13,
        "proditem": false,
        "prodtitle": "Perfumaria",
        "prodcont": 0,
        "prodicon": "graphics/perfumaria.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 14,
        "proditem": false,
        "prodtitle": "Pescados",
        "prodcont": 0,
        "prodicon": "graphics/pescados.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 15,
        "proditem": false,
        "prodtitle": "Pet shop",
        "prodcont": 0,
        "prodicon": "graphics/petshop.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    },
    {
        "prodcd": 16,
        "proditem": false,
        "prodtitle": "Utilidades Domésticas",
        "prodcont": 0,
        "prodicon": "graphics/ud.png",
        "proddesde": "13/03/2018",
        "prodchildren": []
    }
]

2 个答案:

答案 0 :(得分:1)

您的扩展认为您JSON是一个带有results密钥的巨型对象,但实际上您的JSON已经是您尝试流式传输的列表。

因此,您应该将流扩展修改为:.expand((List<Map<String, dynamic>> list) => list)

像:

main.dart

import 'dart:async';
import 'dart:io';
import 'dart:convert';

class Product {
  final String title;

  Product({this.title});

  factory Product.fromJson(Map<String, dynamic> data) {
    return new Product(title: data['prodtitle']);
  }
}

void main() {
  final Stream stream =
      new Stream.fromFuture(new File('products.json').readAsString());

  stream
      .transform(JSON.decoder)
      .expand((List<Map<String, dynamic>> list) => list)
      .map((Map<String, dynamic> data) => new Product.fromJson(data))
      .listen((Product p) => print(p.title));
}

输出

enter image description here

答案 1 :(得分:0)

我尝试了一点,并从Natalie Masse Hooper找到一个可能的解决方案。现在它按预期工作。感谢您的支持。

List produtoList = <Produto>[];

Future<String> loadAssetJson() async{
  return await rootBundle.loadString('assets/produtos.json'); 
}

Future loadProdutos() async{
  String jsonProdutos = await loadAssetJson();
  parseJsonProdutos(jsonProdutos).forEach((f) => produtoList.add(new Produto.fromJson(f)));
}

List parseJsonProdutos(String jsonString){
  List jsonDecoded = JSON.decode(jsonString);
  return jsonDecoded;
}

class Despensa extends StatefulWidget {
  @override
  DespensaState createState() => new DespensaState();
}

class DespensaState extends State<Despensa> {  
  @override
  initState() {
    super.initState();
    loadProdutos();
  }