Handling Network Calls like a Pro in Flutter
If you are already in love with Flutter, you must have created many apps as of now. Some of them are maybe small single screen ones and others can be a full-fledged app. I created many too, at first it all seems easy as they were small apps but once I stepped into creating some bigger apps which are based on doing many network calls I started facing various errors and my app starts misbehaving. This all was happening because I was not handling my API calls properly.
In this blog, We will learn how to overcome all these problems by creating a sample movies app which shows a list of popular movies using TMDB API.
Some Prerequisites
As we are going to implement this app using BLOC pattern you should know the basics of Streams and StreamControllers. Some basic knowledge of HTTP response codes and repository pattern will also be going to help you understand this more easily.
The basic architecture of our Application is going to be like this.
Steps we are going to follow in this article :
- Creating an API base helper class.
- Custom app exceptions.
- MovieResponse model classes.
- A generic API response class.
- A repository class to fetch data from APIs.
- A bloc class for consuming UI events and sending streams.
- A UI to display all the data.
A deep breath here, just before we dive into absolute bliss.
Creating an API base helper class
For making communication between our Remote server and Application we use various APIs which needs some type of HTTP methods to get executed. So we are first going to create a base API helper class, which will be going to help us communicate with our server.
The helper class is self-explanatory. It just contains an HTTP Get method which then can be used by our repository class. You can add other HTTP methods too such as (“POST”, “DELETE”, “PUT”) in this class.
You must be wondering what are all those exceptions? I never heard anything about them. Don’t worry all those are just our custom app exceptions which we are going to create in our next step.
Creating custom app exceptions
An HTTP request on execution can return various types of status codes based on its status. We don’t want our app to misbehave if the request fails so we are going to handle most of them in our app. For doing so are going to create our custom app exceptions which we can throw based on the response status code.
Creating MovieResponse model classes
As we are working with TMDB to get our popular movies. we have to create a basic dart model class which will be going to hold our movie data.
Creating a generic ApiResponse class
In order to expose all those HTTP errors and exceptions to our UI, we are going to create a generic class which encapsulates both the network status and the data coming from the API.
Creating a repository class to fetch data from APIs
As I stated at the start that we are creating this app with a thought of implementing a good architecture. We are going to use a Repository class which going to act as the intermediator and a layer of abstraction between the APIs and the BLOC. The task of the repository is to deliver movies data to the BLOC after fetching it from the API.
Creating the Movie Bloc
For consuming the various UI events and act accordingly, we are going to create a movie bloc. Its task is just to handle the “fetch movie list” event and adding the returned data to the Sink which then can be easily listened by our UI with the help of StreamBuilder.
The main part of blog comes here as we are going to handle all those exceptions that we created. The basic thing that we are doing here is to pass different states of our Data to our UI using the StreamController.
State: Loading -> Notifies the UI that our data is currently loading.
State: Completed -> Notifies the UI that our data is now successfully fetched and we can show it.
State: Error -> Notifies the UI that we got an error or exception while fetching our data.
Creating a Movie Screen to display popular movies
In order to react to the states of our data, we going to create a Stateful widget called MovieScreen and listen to all that state changes using the StreamBuilder.
Things we did in our MovieScreen ->
- Created a new object of our MovieBloc class in initState() method which also going to start fetching our popular movies.
- Disposed our MovieBloc object in dispose() method which going to release all our streams.
- Created a StreamBuilder widget in the body of our Scaffold which going to take the _bloc.movieListStream as the stream and starts listening to any changes in it.
- Handled all the three states of our data using a Switch Case and returning a widget as per the data state.
We did it, our app is now working perfectly and we also handled our network call like a pro. Our users will never be going to suffer now.
You can find the full working code here 👇
Bonus
This practice is not limited to BLOC pattern, It can be easily used with other state management techniques too such as Scoped Model and Provider e.g.:
Then this model can be easily observed using ScopedModelDescendant widget in your UI.
From this blog, I hope I’ve been able to show you how we can easily handle various network calls in our App. If you have any thoughts or questions then please do reach out and I’ll be happy to help!
Do clap 👏 the post as much as you can to show your support and motivate me to write more.
~ Happy Fluttering ~