Search code examples
jsonflutterdartflutter-listview

How to get data from API into listview using model class in Flutter


I am trying to get data from the TMDB API using the model class. I can retrieve the data but I can not show it on listview.

model classes;

top_rated_movies.dart

import 'package:movipedia/model/top_rated_movies/results.dart';

class TopRatedMovies {
  int? page;
  List<Results>? results;
  int? totalPages;
  int? totalResults;

  TopRatedMovies({this.page, this.results, this.totalPages, this.totalResults});

  TopRatedMovies.fromJson(Map<String, dynamic> json) {
    page = json['page'];
    if (json['results'] != null) {
      results = <Results>[];
      json['results'].forEach((v) {
        results!.add(new Results.fromJson(v));
      });
    }
    totalPages = json['total_pages'];
    totalResults = json['total_results'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['page'] = this.page;
    if (this.results != null) {
      data['results'] = this.results!.map((v) => v.toJson()).toList();
    }
    data['total_pages'] = this.totalPages;
    data['total_results'] = this.totalResults;
    return data;
  }
}

results.dart

class Results {
  bool? adult;
  String? backdropPath;
  List<int>? genreIds;
  int? id;
  String? originalLanguage;
  String? originalTitle;
  String? overview;
  double? popularity;
  String? posterPath;
  String? releaseDate;
  String? title;
  bool? video;
  double? voteAverage;
  int? voteCount;

  Results(
      {this.adult,
      this.backdropPath,
      this.genreIds,
      this.id,
      this.originalLanguage,
      this.originalTitle,
      this.overview,
      this.popularity,
      this.posterPath,
      this.releaseDate,
      this.title,
      this.video,
      this.voteAverage,
      this.voteCount});

  Results.fromJson(Map<String, dynamic> json) {
    adult = json['adult'];
    backdropPath = json['backdrop_path'];
    genreIds = json['genre_ids'].cast<int>();
    id = json['id'];
    originalLanguage = json['original_language'];
    originalTitle = json['original_title'];
    overview = json['overview'];
    popularity = json['popularity'];
    posterPath = json['poster_path'];
    releaseDate = json['release_date'];
    title = json['title'];
    video = json['video'];
    voteAverage = json['vote_average'];
    voteCount = json['vote_count'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['adult'] = adult;
    data['backdrop_path'] = backdropPath;
    data['genre_ids'] = genreIds;
    data['id'] = id;
    data['original_language'] = originalLanguage;
    data['original_title'] = originalTitle;
    data['overview'] = overview;
    data['popularity'] = popularity;
    data['poster_path'] = posterPath;
    data['release_date'] = releaseDate;
    data['title'] = title;
    data['video'] = video;
    data['vote_average'] = voteAverage;
    data['vote_count'] = voteCount;
    return data;
  }
}

Listview file; movielist_listview.dart

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:movipedia/model/top_rated_movies/results.dart';

class TopRatedMoviesCircularListView extends StatelessWidget {
  const TopRatedMoviesCircularListView({Key? key}) : super(key: key);

  Future<List<Results>> getTopRatedMovies() async {
    var url =
        "https://api.themoviedb.org/3/discover/movie?api_key=dc92a7524c83f242a3237b2222941f00&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&with_genres=28";
    var response = await Dio().get(url);
    if (response.statusCode == 200) {
      print("print: " + response.data.toString());
    } else {
      print("print: " + response.data.toString());
    }
    var topRatedMovies = response.data;
    final List<Results> results = topRatedMovies['results']
        .map<Results>((json) => Results.fromJson(json))
        .toList();
    return results;
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Results>>(
      future: getTopRatedMovies(),
      builder: (context, snapshot) {
        print('topratedmovies: ' + snapshot.data.toString());
        if (snapshot.hasData) {
          return ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: snapshot.data!.length,
            itemBuilder: (BuildContext context, int index) {
              return Padding(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  children: [
                    Image.network(
                      'https://image.tmdb.org/t/p/w500${snapshot.data![index].posterPath}',
                      width: 100,
                      height: 150,
                      fit: BoxFit.cover,
                    ),
                    Text(
                      snapshot.data![index].title.toString(),
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 16,
                      ),
                    ),
                    Text(
                      'Average Rating: ${snapshot.data![index].voteAverage}',
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 12,
                      ),
                    ),
                    Text(
                      'Release Date: ${snapshot.data![index].releaseDate}',
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 12,
                      ),
                    ),
                  ],
                ),
              );
            },
          );
        } else {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}

I can print the response.data but snapshot.data returns null.

Where am I doing wrong?


Solution

  • Just you need to change your voteAverage data type from double to num because you receive data in int and double both so int value not parse in double type.

    So, change the following code:

    double? voteAverage; 
    

    To

    num? voteAverage;
    

    Here the updated sample code:

    class Results {
          bool? adult;
          String? backdropPath;
          List<int>? genreIds;
          int? id;
          String? originalLanguage;
          String? originalTitle;
          String? overview;
          double? popularity;
          String? posterPath;
          String? releaseDate;
          String? title;
          bool? video;
          num? voteAverage;
          int? voteCount;
    
          Results(
              {this.adult,
                this.backdropPath,
                this.genreIds,
                this.id,
                this.originalLanguage,
                this.originalTitle,
                this.overview,
                this.popularity,
                this.posterPath,
                this.releaseDate,
                this.title,
                this.video,
                this.voteAverage,
                this.voteCount});
    
          Results.fromJson(Map<String, dynamic> json) {
            adult = json['adult'];
            backdropPath = json['backdrop_path'];
            genreIds = json['genre_ids'].cast<int>();
            id = json['id'];
            originalLanguage = json['original_language'];
            originalTitle = json['original_title'];
            overview = json['overview'];
            popularity = json['popularity'];
            posterPath = json['poster_path'];
            releaseDate = json['release_date'];
            title = json['title'];
            video = json['video'];
            voteAverage = json['vote_average'];
            voteCount = json['vote_count'];
          }
    
          Map<String, dynamic> toJson() {
            final Map<String, dynamic> data = <String, dynamic>{};
            data['adult'] = adult;
            data['backdrop_path'] = backdropPath;
            data['genre_ids'] = genreIds;
            data['id'] = id;
            data['original_language'] = originalLanguage;
            data['original_title'] = originalTitle;
            data['overview'] = overview;
            data['popularity'] = popularity;
            data['poster_path'] = posterPath;
            data['release_date'] = releaseDate;
            data['title'] = title;
            data['video'] = video;
            data['vote_average'] = voteAverage;
            data['vote_count'] = voteCount;
            return data;
          }
        }