Hi everyone, in this post, I'll show you how I organize my API call in one class to manage my API endpoint better and pass parameters to them.
If you've got an app that syncs or gets information from a third-party service you must call some API from your code and it is often tempting to write endpoints directly within our HTTP calls, more or less like this:
//Worst case
Future<MyClass> callEndPoint(int id) async {
var response = await http.get(Uri.parse("https://myendpointurl/myclass/$id"));
...
}
//not that much worse
Future<MyClass> callEndPoint(int id) async {
var response = await http.get(Uri.parse("${Env.BASE_URL}/myclass/$id"));
...
}
but it is not good practice to hardcode endpoints in all calls, and it is a tad better to manage an environment variable or constant that defines our BASE_URL
for calls.
My solution
The solution I have adopted for some time in all my projects is to create an ApiEndPoint class where I define all my endpoints and the parameters I need to manage. So for example to implement calls to the Star Wars API I can do it this way:
class ApiEndPoint {
late String FILM_ALL;
late String FILM_SINGLE;
ApiEndPoint({int? id}) {
//Value added for simplicity but it is always better
// to add it in a configuration file
String baseUrlPath = 'https://swapi.dev/api';
FILM_ALL = '$baseUrlPath/films/';
FILM_SINGLE = '$baseUrlPath/films/$id';
}
}
That way when I need to call the endpoint to get the list of movies I just type in:
Future<List<Film>> getAllFilms() async {
var response = await http.get(
Uri.parse(ApiEndPoint().FILM_ALL),
);
//...
}
And if this endpoint requires input parameters, such as the endpoint to get the information about a single movie, simply write:
Future<Film> getSingleFilm(int idFilm) async {
var response = await http.get(
Uri.parse(ApiEndPoint(id: idFilm).FILM_SINGLE),
);
//...
}
Easy isn't it?
I find this setup useful and with the following advantages:
I have a single class with the responsibility of managing my EndPoints and organizing the paths as required by the API;
I can easily pass input parameters without worrying about URL formatting;
In my repositories and in my HTTP calls I can tell right away what API it is without going to the URL to figure it out because I have made it explicit in the attributes of my ApiEndPoint class;
In the most extreme case, I can switch to another API without having to change my HTTP calls but only by changing the URLs within the ApiEndPoint class;
Code strong, Alberto
Cover Photo by Maria Orlova: Corner Of Aged House Near Direction Post In Town