简体   繁体   中英

JSON data from API call doesn't show in ListView FutureBuilder Flutter

My Json response status code is 200 and the object is also created but when I try to bind it with UI in ListView it doesn't show anything. I have used quicktype.io to parse my json data that I received from the API call.

Here's my API_manager.dart file:

import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';

// ignore: camel_case_types
class API_Manager {
  Future<ContactsModel> getContacts() async {
    var client = http.Client();
    var contactsModel;
    String contacts_url =
        'https://exampleapi.com';
    String basicAuth = 'Basic auth key example';
    try {
      var response = await client.get(contacts_url,
          headers: <String, String>{'authorization': basicAuth});
      print(response.statusCode);
      if (response.statusCode == 200) {
        var jsonString = response.body;
        var jsonMap = json.decode(jsonString);
        contactsModel = contactsModel.fromJson(jsonMap);
      }
    } catch (Exception) {
      return contactsModel;
    }
    return contactsModel;
  }
}

My UI code:

import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';

class ContactsPage extends StatefulWidget {
  @override
  _ContactsPageState createState() => _ContactsPageState();
}

class _ContactsPageState extends State<ContactsPage>
    with SingleTickerProviderStateMixin {
  Future<ContactsModel> _contactsModel;
  bool isSearching = false;
  TabController _tabController;

  @override
  void initState() {
    // TODO: implement initState

    super.initState();
    _tabController = TabController(length: 2, initialIndex: 0, vsync: this);
    _tabController.addListener(_handleTabIndex);
  }

  @override
  void dispose() {
    _tabController.removeListener(_handleTabIndex);
    _tabController.dispose();
    super.dispose();
  }

  void _handleTabIndex() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    _contactsModel = API_Manager().getContacts();
    return DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            title: Text('Contacts'),
            bottom: PreferredSize(
                child: Align(
                  alignment: Alignment.centerLeft,
                  child: TabBar(
                    controller: _tabController,
                    isScrollable: true,
                    unselectedLabelColor: Colors.white.withOpacity(0.3),
                    indicatorColor: Colors.white,
                    tabs: [
                      Tab(
                        child: Text('Contacts'),
                      ),
                      Tab(
                        child: Text('Companies'),
                      )
                    ],
                  ),
                ),
                preferredSize: Size.fromHeight(40.0)),
            actions: <Widget>[
              Padding(
                padding: const EdgeInsets.only(right: 16.0),
                child: IconButton(
                  icon: Icon(Icons.search),
                  color: Colors.white,
                  onPressed: () {},
                ),
              ),
            ],
          ),
          body: TabBarView(controller: _tabController, children: <Widget>[
            Container(
                height: double.infinity,
                child: FutureBuilder<ContactsModel>(
                    future: _contactsModel,
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                        return ListView.builder(
                            padding: const EdgeInsets.all(6),
                            itemCount: snapshot.data.contacts.length,
                            itemBuilder: (context, index) {
                              var contact = snapshot.data.contacts[index];
                              return Container(
                                height: 100,
                                color: Colors.white,
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.start,
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    Text(contact.owner.username,
                                        style: TextStyle(fontSize: 16))
                                  ],
                                ),
                              );
                            });
                      } else
                        return Center(child: CircularProgressIndicator());
                    })),
            Container(
                height: double.infinity,
                child: ListView(
                  padding: const EdgeInsets.all(6),
                  children: <Widget>[
                    InkWell(
                      onTap: () {
                        Navigator.push(context,
                            MaterialPageRoute(builder: (_) => ViewCompany()));
                      },
                      child: Container(
                        height: 50,
                        color: Colors.white,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(
                              'Example company',
                              style: TextStyle(fontSize: 16),
                            ),
                            Text(
                              'Example company',
                              style: TextStyle(fontSize: 14),
                            )
                          ],
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 5,
                    ),
                    InkWell(
                      onTap: () {
                        Navigator.push(context,
                            MaterialPageRoute(builder: (_) => ViewCompany()));
                      },
                      child: Container(
                        height: 50,
                        color: Colors.white,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(
                              'example',
                              style: TextStyle(fontSize: 16),
                            ),
                            Text(
                              'example',
                              style: TextStyle(fontSize: 14),
                            )
                          ],
                        ),
                      ),
                    ),
                  ],
                )),
          ]),
          floatingActionButton: _bottomButtons(),
        ));
  }

  Widget _bottomButtons() {
    return _tabController.index == 0
        ? FloatingActionButton(
            shape: StadiumBorder(),
            onPressed: () {
              Navigator.push(context, MaterialPageRoute(builder: (_) {
                return AddContacts();
              }));
            },
            backgroundColor: Colors.cyan,
            child: Icon(
              Icons.person_add,
              color: Colors.white,
            ))
        : FloatingActionButton(
            shape: StadiumBorder(),
            onPressed: () {
              Navigator.push(context, MaterialPageRoute(builder: (_) {
                return AddCompany();
              }));
            },
            backgroundColor: Colors.cyan,
            child: Icon(
              Icons.add,
              color: Colors.white,
            ),
          );
  }
}

Created model(contactsModel.dart):

import 'dart:convert';

ContactsModel contactsModelFromJson(String str) => ContactsModel.fromJson(json.decode(str));

String contactsModelToJson(ContactsModel data) => json.encode(data.toJson());

class ContactsModel {
  ContactsModel({
    this.total,
    this.contacts,
  });

  String total;
  Map<String, Contact> contacts;

  factory ContactsModel.fromJson(Map<String, dynamic> json) => ContactsModel(
    total: json["total"],
    contacts: Map.from(json["contacts"]).map((k, v) => MapEntry<String, Contact>(k, Contact.fromJson(v))),
  );

  Map<String, dynamic> toJson() => {
    "total": total,
    "contacts": Map.from(contacts).map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
  };
}

class Contact {
  Contact({
    this.isPublished,
    this.dateAdded,
    this.dateModified,
    this.createdBy,
    this.createdByUser,
    this.modifiedBy,
    this.modifiedByUser,
    this.id,
    this.points,
    this.color,
    this.fields,
    this.lastActive,
    this.owner,
    this.ipAddresses,
    this.tags,
    this.utmtags,
    this.stage,
    this.dateIdentified,
    this.preferredProfileImage,
    this.doNotContact,
    this.frequencyRules,
  });

  bool isPublished;
  DateTime dateAdded;
  DateTime dateModified;
  int createdBy;
  String createdByUser;
  int modifiedBy;
  String modifiedByUser;
  int id;
  int points;
  dynamic color;
  Fields fields;
  dynamic lastActive;
  Owner owner;
  List<dynamic> ipAddresses;
  List<Tag> tags;
  List<dynamic> utmtags;
  Stage stage;
  DateTime dateIdentified;
  dynamic preferredProfileImage;
  List<dynamic> doNotContact;
  List<dynamic> frequencyRules;

  factory Contact.fromJson(Map<String, dynamic> json) => Contact(
    isPublished: json["isPublished"],
    dateAdded: DateTime.parse(json["dateAdded"]),
    dateModified: json["dateModified"] == null ? null : DateTime.parse(json["dateModified"]),
    createdBy: json["createdBy"],
    createdByUser: json["createdByUser"],
    modifiedBy: json["modifiedBy"] == null ? null : json["modifiedBy"],
    modifiedByUser: json["modifiedByUser"] == null ? null : json["modifiedByUser"],
    id: json["id"],
    points: json["points"],
    color: json["color"],
    fields: Fields.fromJson(json["fields"]),
    lastActive: json["lastActive"],
    owner: Owner.fromJson(json["owner"]),
    ipAddresses: List<dynamic>.from(json["ipAddresses"].map((x) => x)),
    tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
    utmtags: List<dynamic>.from(json["utmtags"].map((x) => x)),
    stage: Stage.fromJson(json["stage"]),
    dateIdentified: DateTime.parse(json["dateIdentified"]),
    preferredProfileImage: json["preferredProfileImage"],
    doNotContact: List<dynamic>.from(json["doNotContact"].map((x) => x)),
    frequencyRules: List<dynamic>.from(json["frequencyRules"].map((x) => x)),
  );

  Map<String, dynamic> toJson() => {
    "isPublished": isPublished,
    "dateAdded": dateAdded.toIso8601String(),
    "dateModified": dateModified == null ? null : dateModified.toIso8601String(),
    "createdBy": createdBy,
    "createdByUser": createdByUser,
    "modifiedBy": modifiedBy == null ? null : modifiedBy,
    "modifiedByUser": modifiedByUser == null ? null : modifiedByUser,
    "id": id,
    "points": points,
    "color": color,
    "fields": fields.toJson(),
    "lastActive": lastActive,
    "owner": owner.toJson(),
    "ipAddresses": List<dynamic>.from(ipAddresses.map((x) => x)),
    "tags": List<dynamic>.from(tags.map((x) => x.toJson())),
    "utmtags": List<dynamic>.from(utmtags.map((x) => x)),
    "stage": stage.toJson(),
    "dateIdentified": dateIdentified.toIso8601String(),
    "preferredProfileImage": preferredProfileImage,
    "doNotContact": List<dynamic>.from(doNotContact.map((x) => x)),
    "frequencyRules": List<dynamic>.from(frequencyRules.map((x) => x)),
  };
}
class ......{}

Output Screen: here

Json Viewer: here

Dart Devtools: here

This is probably not a problem with your json parsing, but a UI issue. Putting Columns or Rows inside ListViews or the opposite. If there was something wrong with the json, you'd be seeing the return Center(child: CircularProgressIndicator()); ,

But instead, you're getting an empty UI. Check your debug console, if you have RenderView errors, or failed to layout render-box issues, this will be the cause of them.

Try using the property of shrink wrap in your lists:

ListView(shrinkwrap:true...

and

ListView.builder(shirinkrap:true...

Also, wrap your Row that inside the ListView with a LimitedBox

ie

LimitedBox(
  child: Row(
  mainAxisAlignment: MainAxisAlignment.start,
   children: [

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM