Convert Single API reponse to a list of Maps to co

2019-08-17 14:58发布

问题:

I have used the flutter cookbook to create a Future in order to convert a single Map into a card. However I want to do this with a list of Maps. I know I need to create a list and then use the futurebuilder to return a list view, but I am unsure how to add to the apitest() method to add each Map to a list to then convert. Any help is much appreciated.

This is main.dart:

import 'package:flutter/material.dart';

import './viewviews.dart';

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(
      title: 'API TEST',
      theme: new ThemeData(
        primarySwatch: Colors.purple,
        backgroundColor: Colors.black,
      ),
      home: CardPage(),
    );
  }
}

This is my class to construct the object:

import 'package:flutter/material.dart';

class Post {
  final String appName;
  final String brandName;
  final int views;

  Post(
      {@required this.appName, @required this.brandName, @required this.views});

  factory Post.fromJson(Map<String, dynamic> json) {
    return (Post(
        views: json['Views'],
        brandName: json['brandname'],
        appName: json['appname']));
  }
}

and finally the code I am using to make the api call and use the futurebuilder:

import 'dart:async';

//final List<Post> cardslist = [];

class CardPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        appBar: AppBar(title: Text('API TEST')),
        body: ListView.builder(
          itemBuilder: cardbuilder,
          itemCount: 1,
        ));
  }
}

Future<Post> testapi() async {
  final apiresponse =
      await http.get('https://myriadapp-55adf.firebaseio.com/Views.json');
  print(apiresponse.body);
  return Post.fromJson(json.decode(apiresponse.body));
}

Widget cardbuilder(BuildContext context, int index) {
  return Container(
      margin: EdgeInsets.all(20.0),
      child: FutureBuilder<Post>(
          future: testapi(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text(snapshot.data.appName);
            } else if (snapshot.hasError) {
              return Text(snapshot.hasError.toString());
            }
            return Center(child: CircularProgressIndicator());
          }));
}

I have commented out the code to create the list but I know I will need this, I just need to decode the json to add a list of Maps to it and then use Futurebuilder to return the listview. Thank you.

回答1:

Your json doesn't actually return a json array, it actually returns a map with arbitrary key names like View1, so we'll iterate that map. You need to hoist your FutureBuilder up to the point where you can deal with the whole json at once, so at the page level. So CardPage becomes

class CardPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('API TEST')),
      body: FutureBuilder<Map>(
        future: fetchData(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            final Map<String, dynamic> data = snapshot.data;
            final List<Container> cards = data.keys
                .map((String s) => makeCard(Post.fromJson(data[s])))
                .toList();
            return ListView(
              children: cards,
            );
          } else if (snapshot.hasError) {
            return Text(snapshot.hasError.toString());
          }
          return const Center(
            child: CircularProgressIndicator(),
          );
        },
      ),
    );
  }

  Container makeCard(Post post) {
    return Container(
      margin: EdgeInsets.all(20.0),
      child: Text(post.appName),
    );
  }

  Future<Map> fetchData() async {
    final apiresponse =
        await http.get('https://myriadapp-55adf.firebaseio.com/Views.json');
    print(apiresponse.body);
    return json.decode(apiresponse.body);
  }
}