API Integration was a popular demand so this tutorial will teach you the easiest way to integrate an API with a flutter app.





Our objective for this tutorial is to link our static app to TMDb in the easiest way possible. So we won’t go through state management, dependency injection and other “advanced topics”.

Adding the depedencies:

Inside your pubscpec.yaml file make sure to add the http package:

http:

This package is used to make http requests.

API Integration Service:

Start by creating a file named “api.dart”. Inside create a class named Api. The Api class will be responsible of calling the backend everytime you call one of it’s functions.

Inside this class set these variables:

static const url = “https://api.themoviedb.org/3”; static const apiKey = “YourAPI”;

Even though it’s self-explanatory I will say that “url” is the base url of our endpoint, and apiKey is the key you got from TMDb.

Now define your first function and name it: “getGenreList()” (The name doesn’t matter it’s up to you). Make sure the function is Async as it returns a future.

This function returns a Future of type List of type GenreModel. We will take a look at the models in a second.

Now begin by setting a final variable called response as follows:

final response = await http.get('$url/genre/movie/list?api_key=$apiKey');

http.get needs a url which here is our base url + /genre/movie/list which is the path to get all the known movies genres in the backend + apiKey.

Then check if the response status code is 200 which in http basically means everything went OK.

If so then we you parse the returned data like so:

final parsed = json.decode(response.body)['genres'].cast >();

Then return it as a list as you can see here:

return parsed .map ((json) => GenreModel.fromJson(json)) .toList();

The second function in the class is getFeaturedMovies() which is very similar to the first one so we won’t go through it.

The last function has only one difference, it doesn’t return a List thus you don’t have to cast it.

Future getMovieInfo(int movieId) async{ final response = await http.get("$url/movie/$movieId?api_key=$apiKey"); if (response.statusCode == 200){ return MovieModel.fromJson(json.decode(response.body)); } else{ throw Exception('Failed to load Movie Information'); } }

Your whole class should look like this:

import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:movie_db/models/moviemodel.dart'; import 'package:movie_db/models/featuredmoviemodel.dart'; import 'models/genremodel.dart'; class Api { static const url = "https://api.themoviedb.org/3"; static const apiKey = "f476c933beeb792de073665402a501ad"; Future > getGenreList() async { final response = await http.get('$url/genre/movie/list?api_key=$apiKey'); if (response.statusCode == 200) { final parsed = json.decode(response.body)['genres'].cast >(); return parsed .map ((json) => GenreModel.fromJson(json)) .toList(); } else { // If that response was not OK, throw an error. throw Exception('Failed to load post'); } } Future > getFeaturedMovies() async { final response = await http.get('$url/trending/movie/day?api_key=$apiKey'); print(response.body); if (response.statusCode == 200) { final parsed = json.decode(response.body)['results'].cast >(); print(parsed); return parsed .map ((json) => FeaturedMovieModel.fromJson(json)) .toList(); } else { throw Exception('Failed to load featured movies'); } } Future getMovieInfo(int movieId) async{ final response = await http.get("$url/movie/$movieId?api_key=$apiKey"); if (response.statusCode == 200){ return MovieModel.fromJson(json.decode(response.body)); } else{ throw Exception('Failed to load Movie Information'); } } }

Models:

Models here will allow you to set the data you got from Json to actual variables inside the class.

Take a look at the GenreModel which is the simplest one:

class GenreModel { final String name; final int id; GenreModel({this.name, this.id}); factory GenreModel.fromJson(Map json) { return GenreModel( id: json['id'], name: json['name'], ); } }

Once called the API returns the genre name as “name” and it’s id as “id” and this basically sets it as variables inside the GenreModel Class.

The other models are basically the same but with more variables.

FutureBuilder:

Now that we have finished with the API Intergration we have to link the UI to it.

Let’s take the example of the home screen.

Start by making your Home Screen widget stateful. Declare the needed variables such as:

Future > featuredMovies; Future > genreList; Api _api;

In your InitState function:

@override void initState() { super.initState(); _api = Api(); featuredMovies = _api.getFeaturedMovies(); genreList = _api.getGenreList(); }

Now basically what is left is to wrap the widgets that need the data in a FutureBuilder widget:

FutureBuilder >( future: featuredMovies, builder: (context, snapshot) { if (snapshot.hasData) { return HomePageFeaturedWidget(snapshot: snapshot); } else { return Center(child: CircularProgressIndicator()); } }, ),

What this is doing is taking the our future and waiting for it, as long as it has no data it shows a CircularProgressIndicator. Then once it gets data it switches to HomePageFeaturedWidget and passes the data snapshot as a variable.

The HomePageFeaturedWidget then displays the data accordingly:

import 'package:flutter/material.dart'; import 'package:movie_db/models/featuredmoviemodel.dart'; import 'package:movie_db/global.dart'; class HomePageFeaturedWidget extends StatelessWidget { final AsyncSnapshot > snapshot; const HomePageFeaturedWidget({ Key key, this.snapshot, }) : super(key: key); @override Widget build(BuildContext context) { return PageView.builder( itemCount: snapshot.data.length, itemBuilder: (ctx, id) { return Container( margin: EdgeInsets.all(15.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15.0), boxShadow: [ BoxShadow( blurRadius: 5.0, color: Colors.grey[400], offset: Offset(0, 3)) ], ), child: Stack( children: [ Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular(15.0), child: Image.network( // movieList[id]['img'], getPosterImage(snapshot.data[id].poster_path), fit: BoxFit.cover, ), ), ), Positioned( bottom: 0, left: 0, right: 0, child: Container( padding: EdgeInsets.all(15.0), decoration: BoxDecoration( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(15), bottomRight: Radius.circular(15), ), color: Colors.black45, ), child: Text( "${snapshot.data[id].original_title}", style: TextStyle( color: Colors.white, fontSize: 23, ), softWrap: true, maxLines: 2, overflow: TextOverflow.ellipsis, ), ), ) ], ), ); }, ); } }

Once special thing here is that the poster image we get from the API isn’t the full url so create a getPosterImage function in your global.dart folder (this is just an example it could be anywhere).

String getPosterImage(String input){ return "https://image.tmdb.org/t/p/original/$input"; }

This function is specific to the TMDb api and returns the full image url.

Source Code:

As promised here is the source code of the project: https://github.com/cybdom/netflixy_flutter

If you found this to be helpful donate at: https://www.buymeacoffee.com/bi3cp0Zk5

Conclusion:

If you have a simple app, or getting started with flutter is the easiest way to API Integration. However, for maintainability and big complex projects I wouldn’t recommend this approach.

In the future tutorials we will do the same but using the Provider Package which is a much better approach in my opinion.

Thank you for following along, please feel free to ask any questions, suggestions or Fix any errors I’ve made.

Make sure to follow me on Twitter to be notified of upcoming tutorial: https://twitter.com/cybdom