I am trying to create a class to display a movie title and poster in a card. I am using the TMDB API. here are my dart files-
movie.dart
class Movie{
String mtitle;
String mposter;
Movie({required this.mtitle, required this.mposter});
}
MovieCard.dart
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables
import 'package:flutter/material.dart';
import 'package:movie_recommendation_ia/objects/movie.dart';
class MovieCard extends StatelessWidget {
MovieCard({required this.movie,});
final Movie movie;
@override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Container(
child: Image.network(
movie.mposter,
height: 150.0,
width: 120.0,
fit: BoxFit.cover,
),
),
Text(
movie.mtitle
)
],
),
),
);
}
}
getMovie.dart
// ignore_for_file: file_names
import 'dart:async';
import 'package:movie_recommendation_ia/objects/movie.dart';
import 'package:tmdb_api/tmdb_api.dart';
import 'package:http/http.dart';
import 'dart:convert';
class getMovie{
String? poster;
String title='';
final String APIKey = 'placeholder';
final String readAccessToken = 'placeholder';
Future<Movie> loadMovie() async{
Response response = await get(Uri.parse('https://api.themoviedb.org/3/movie/550?api_key=$APIKey'));
Map data = jsonDecode(response.body);
//print (data['poster_path']);
TMDB tmdbWithCustomLogs = TMDB(
ApiKeys(APIKey, readAccessToken),
logConfig: const ConfigLogger(
showLogs: true,
showErrorLogs: true
)
);
poster = await tmdbWithCustomLogs.images.getUrl(data['poster_path']);
title = data['title'];
Movie set = Movie(mtitle: title, mposter: poster as String);
return set;
//print(poster);
//print(title);
}
}
recommended.dart
import 'package:flutter/material.dart';
import 'package:movie_recommendation_ia/objects/movie.dart';
import 'package:movie_recommendation_ia/objects/MovieCard.dart';
import 'package:movie_recommendation_ia/objects/getMovie.dart';
class Recommended extends StatefulWidget {
const Recommended({super.key});
@override
State<Recommended> createState() => _RecommendedState();
}
class _RecommendedState extends State<Recommended> {
@override
void initState() {
// TODO: implement initState
super.initState();
}
load() async {
Movie get = await getMovie().loadMovie();
return get;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
title: Column(
children: [
TextButton(
onPressed: (){
Navigator.pushNamed(context, '/search');
},
child: const Text(
'Search',
style: TextStyle(
color: Colors.white
),
)
),
Row(
children: <Widget>[
Expanded(
child: TextButton(
onPressed: (){
Navigator.pushReplacementNamed(context, '/following');
},
child: const Text(
'Following',
style: TextStyle(
color: Colors.white
),
)
),
),
Expanded(
child: TextButton(
onPressed: (){
Navigator.pushReplacementNamed(context, '/recommended');
},
child: const Text(
'Recommended',
style: TextStyle(
color: Colors.white
),
)
),
),
Expanded(
child: TextButton(
onPressed: (){
Navigator.pushReplacementNamed(context, '/myactivity');
},
child: const Text(
'My Activity',
style: TextStyle(
color: Colors.white
),
)
),
),
],
),
],
),
),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
MovieCard(movie: load(),)
],
)
],
)
);
}
}
I created an object called Movie which would have the properties title and poster, I used the object in a different class called MovieCard. I used an asynchronous function to fetch the title and poster url from the API. I wanted to put these in the Movie object and then the MovieCard object. When I run, I get an exception: "_TypeError (type ‘Future’ is not a subtype of type ‘Movie’)". I realize that this did not work because the async function is of type Future, but I cant figure out how to fix this.
2
Answers
You are basically passing a
Future
instead of aMovie
object in yourMovieCard
.In your state class, please adjust like this:
You can safely remove the
load
method.Also a minor but useful adjustment recommended: you should rename the
getMovie
class toGetMovie
as class names should be PascalCase in Dart.Use Future builder to load UI which depends on data from Future/API.
NOTE: Using setState after getting data and updating UI will rebuild the whole widget which is not recommended method to follow.