Home > Software engineering >  ListView.builder not showing JSON response data
ListView.builder not showing JSON response data

Time:06-21

I am trying to get data from an API

Here you have the API Call:

Future<List<Clinica>> fetchClinicas(String idUsuario) async {

  print("USUARIO ID EN FETCHCLINICAS "   idUsuario);
  String url = Constantes().URLProyecto Constantes().APICarpeta "get_clinicas.php?usuario=" idUsuario;
  final response = await http.get(Uri.parse(url));
  print("RESPONSE BODY CLINICAS "  response.body.toString());

  return clinicaFromJson(response.body);

}

The output from the response.body is

I/flutter (13249): RESPONSE BODY CLINICAS [{"id_clinica":"9","nombre_clinica":"Centro de Fisioterapia de Pruebas Capenergy 2","direccion_clinica":"Avinguda Mare de D\u00e9u de Montserrat, 41Bis (Pasaje), 08970 Sant Joan Desp\u00ed, Barcelona, Espa\u00f1a","tel_clinica":"934774348","cod_clinica":"TEST-002","fecha_ingreso_clinica":"2019-05-15","visiblePacientes":"1","visibleAgenda":"0","visibleForo":"1","visibleSAT":"1","logo_clinica":"qT3cKFdescarga.png"}]

That means that the response is not empty.

Then I am trying to show the downloaded items on a ListView.builder, but the snapshot is empty.

               Expanded(
                  child: Container(
                    child: FutureBuilder(
                      future: fetchClinicas(miId),
                      builder: (context, snapshot) {
                        print("SNAPSHOT   "   snapshot.hasData.toString());

                        if (snapshot.hasData) {
                          print("estoy en snapshot has data");
                          List<dynamic>? filteredList = snapshot.data as List?;
                          filteredList ??= [];
                          return ListView.builder(
                            itemCount: filteredList.length,
                            shrinkWrap: true,
                            itemBuilder: (BuildContext context, index) {
                              print(index.toString());
                              Clinica clinica = filteredList![index];



                              return new GestureDetector(
                         ...
                   
                        }
return Image.asset(
                          "assets/images/vacio.png",
                          fit: BoxFit.contain,
                        );
                      },

I am always getting as result the image.asset which is loading if snatshot has no data.

EDIT

Here you have Clinica model class:

import 'dart:convert';

List<Clinica> clinicaFromJson(String str) => List<Clinica>.from(json.decode(str).map((x) => Clinica.fromJson(x)));

String clinicaToJson(List<Clinica> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Clinica {
  Clinica({
    required this.idClinica,
    required this.nombreClinica,
    required this.direccionClinica,
    required this.telClinica,
    required this.emailClinica,
    required this.codClinica,
    required this.fechaIngresoClinica,
    required this.logoClinica,
    required this.visiblePacientes,
    required this.visibleAgenda,
    required this.visibleForo,
    required this.visibleSAT
  });

  String idClinica;
  String nombreClinica;
  String direccionClinica;
  String telClinica;
  String emailClinica;
  String codClinica;
  DateTime fechaIngresoClinica;
  String logoClinica;
  String visiblePacientes;
  String visibleAgenda;
  String visibleForo;
  String visibleSAT;

  factory Clinica.fromJson(Map<String, dynamic> json) => Clinica(
    idClinica: json["id_clinica"],
    nombreClinica: json["nombre_clinica"],
    direccionClinica: json["direccion_clinica"],
    telClinica: json["tel_clinica"],
    emailClinica: json["email_clinica"],
    codClinica: json["cod_clinica"],
    fechaIngresoClinica: DateTime.parse(json["fecha_ingreso_clinica"]),
    logoClinica: json["logo_clinica"],
    visiblePacientes: json["visiblePacientes"],
    visibleAgenda: json["visibleAgenda"],
    visibleForo: json["visibleForo"],
    visibleSAT: json["visibleSAT"],
  );

  Map<String, dynamic> toJson() => {
    "id_clinica": idClinica,
    "nombre_clinica": nombreClinica,
    "direccion_clinica": direccionClinica,
    "tel_clinica": telClinica,
    "email_clinica": emailClinica,
    "cod_clinica": codClinica,
    "fecha_ingreso_clinica": "${fechaIngresoClinica.year.toString().padLeft(4, '0')}-${fechaIngresoClinica.month.toString().padLeft(2, '0')}-${fechaIngresoClinica.day.toString().padLeft(2, '0')}",
    "logo_clinica": logoClinica,
    "visiblePacientes": visiblePacientes,
    "visibleAgenda": visibleAgenda,
    "visibleForo": visibleForo,
    "visibleSAT": visibleSAT,
  };
}

CodePudding user response:

Data doesn't have "email_clinica" while the model expects that. Mark it as optional.

...
  String telClinica;
  String? emailClinica;
  String codClinica;
...

CodePudding user response:

Here I'm displaying a simple fetch of a list of posts and converting them to a list and displaying it in a ListView.builder

Api Service:

static Future<List<PostModel>> fetchPosts({
    required int pageNum,
  }) async {
    var url = Config.apiUrl   Config.postsUrl   pageNum.toString();
// here we're fetching the data from the api
    var response = await http.get(
      Uri.parse(url),
    );

// checking if the call is a success or not
    if (response.statusCode == 200) {
// if yes then get the body from the response and fill the method 
// where we convert the data to an actual list of a model in the 
// PostsModel class
      var jsonString = response.body;

      return postsFromJson(jsonString);
    } else {
      List<PostModel> emptyList = [];
      return emptyList;
    }
  }

PostsModel:

// here we are decoding the body of the response and converting
// to a list of that Model
List<PostModel> postsFromJson(String str) => List<PostModel>.from(
      json.decode(str).map(
            (x) => PostModel.fromJson(x),
          ),
    );

class PostModel {
  int? id;
  String? title;
  dynamic imageUrl;
  String? postedDate;
  String? author;
  String? postContent;

  PostModel({
    required this.id,
    required this.title,
    required this.imageUrl,
    required this.postedDate,
    required this.author,
    required this.postContent,
  });
// here we can find the fromJson method which converts the json into
 // a dart objcet which in my case here is a PostModel
  PostModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    title = json['title']['rendered'];
    imageUrl = json["_embedded"]["wp:featuredmedia"] == null
        ? 'https://pergjigje.net/wp-content/uploads/2021/09/Logo-e-544.png'
        : json["_embedded"]["wp:featuredmedia"][0]["source_url"];
    postedDate = DateFormat('MMMM d, yyyy').format(
      DateTime.parse(
        json['date'],
      ),
    );
    author = json["_embedded"]["author"][0]["name"];
    if (json['content']['rendered'] != null) {
      postContent = json['content']['rendered'];
    }
  }

  PostModel.searchFromJson(
      Map<String, dynamic> json, Map<String, dynamic> searchMediaJson) {
    id = json['id'];
    title = json['title']['rendered'];
    imageUrl = searchMediaJson['source_url'] == null
        ? 'https://via.placeholder.com/300x150.png'
        : json['source_url'];
    postedDate = DateFormat('MMMM d, yyyy').format(
      DateTime.parse(
        json['date'],
      ),
    );
    author = json["_embedded"]["author"][0]["name"];
    if (json['content']['rendered'] != null) {
      postContent = json['content']['rendered'];
    }
  }
}

My postsController(Because I use GetX as a state manager):


// In the controller we call the method which we created in the
 //services and fill a local list with its result
// you can call this in the **initState()** btw or put it in a 
//**FutureBuilder()**
  Future<void> fetchPosts({
    int? pageNum = 0,
  }) async {
    try {
      if (postsList.isEmpty || pageNum == 0) {
        isLoading(true);
        postsList.clear();
      }

      var posts = await ApiServices.fetchPosts(
        pageNum: pageNum!.toInt(),
      );

      if (posts.isNotEmpty) {
        _page  = 5;
// Here we are filling the local postsList with the list from the 
//apiService 
        postsList.assignAll(posts);
      }
    } finally {
      isLoading(false);
    }
  }

Listview.builder:

                  child: ListView.builder(
// Here we are giving the length of the local list we filled in the
 //controller
                    itemCount: postsController.postsList.length,
                    shrinkWrap: true,
                    controller: _postsController.scrollController,
                    itemBuilder: (context, index) {
// And finally we are using the data from the list to display in the screen
                      var data = postsController.postsList[index];
                      if (index == postsController.postsList.length - 1) {
                        return const Padding(
                          padding: EdgeInsets.all(10.0),
                          child: CostumeProgressIndicator(),
                        );
                      } else {
                        return PostItemWidget(
                          data: data,
                          index: index,
                        );
                      }
                    },
                  ),
  • Related