Networking In Flutter : Dio & GetX State mixin | Flutter 3.3.5

What is Dio? Why choose Dio over HTTP? How to Perform CRUD operation using Dio? How to Handle Dio Errors easily? What is GetX State mixin ? — A Complete Beginners Guide 2022 🐥

Sinnoor C
6 min readNov 7, 2022

Why choose Dio over HTTP ❓

If you’re looking for a quick response to this, then let me say that it’s because Dio offers more features than HTTP. Dio provides a lot of capabilities that HTTP lacks. Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout, and so on.

Dependency Installation 💡

Install the dependencies listed below.

Run flutter pub get and you are ready to go.

Folder Structure 📂

It is advised that we follow a set structure when working on a large project.

dummyJSON

We will be using dummyJSON API in our example. This API provides all sorts of methods that we wanted: GET, POST, PUT, DELETE.

visit dummyJson for more info ℹ️

Api Service 🌐

To send a request to the server, we must first create a Client. A client may be thought of as a middleman who makes requests and then responds to us.

Here we can set the Base Url, Connection Timeout, Receive Timeout, and other options. As a result, we won’t have to send all of these parameters in every request.

Head over to lib > app > data > network > service and create an api_service.dart file in it.

Create a Dio instance and assign different parameters inside the constructor as below:

  • Here you will be getting an error saying, ApiUrl is not defined.
  • To solve that, head over to lib > app > constants and create a file named app_constants.dart.
  • In this, we will define all the endpoints that we want to use in our application

Creating (GET, POST, PUT, DELETE) Methods 📍

Now that we’ve configured the Dio instance, it’s time to create HTTP methods.

Let’s create a GET method first inside the same ApiService class.

URL

There is only one required parameter in Get method, URL. Whenever we want to make a GET request we need to pass that path from which we want a response back.

Query Parameter

You can also define different query parameters if that is the case in your project. For example in some cases, the path could be: https://abcapi.com/user?name=sinnoor. Here name is the query parameter and you can pass this parameter in queryParameter in Map format: { 'name' : 'sinnoor' }

Options

The Options describe the HTTP request information and configuration. We can pass basic configurations like Headers, Method Type, Content-Type, Response Type, etc.

Cancel Token

You can cancel a request by using a cancel token. One token can be shared with different requests. when a token’s [cancel] method is invoked, all requests with this token will be canceled.

onReceiveProgress

This is a callback which is used to listen the progress for sending/receiving data. It has two parameters.

countIndicates the length of the bytes that have been sent/received.

Total Indicates the length of the response/body.

📍You don’t need to use these types of callback if you are doing a simple task. I’m just mentioning, so that you should know that it exists.

So these are the parameters that we are using in order to make a get request 👨🏻‍💻

We are also catching the error on SocketException, FormatException. are going to handle different errors further in this article ⚠️

Now let’s define the remaining 3 methods 💡

POST

While making GET requests we don’t pass any data usually. But when making the request like POST, PUT, DELETE we need to pass the body/data.

The parameters will remain same for all these 3 methods (POST, PUT, DELETE ) only the type of method will change (i.e _dio.post(), _dio.put(), _dio.delete() ).💡

Model Creation 👤

We need to develop a model for the data we’re obtaining from the server in order to parse it in a Dart-readable format.

user_model.dart. 👈 here you can see the model class that i created .

📍 I’ve used Dart Model Generator for creating the above models.

API Request Class 🌐

Now that we are all set to make an API request. Let’s head over to lib > app> data > network > api and create a user folder and inside it create a user_api.dart file.

💡 In this, We are going to define different API request methods which will directly call the client’s method and will return the RAW data. Notice I said the methods defined in this class will return the RAW data, not the model that we created earlier.

  • As you can see, the code is pretty straightforward. We are simply calling different methods of the ApiService by passing the required path/endpoint.
  • As we have already defined the base URL in the ApiService , we only need to pass the rest of the Endpoint and not the full URL.
  • For the POST method the required data is passed in Map format.
  • For the PUT method we need an Id, which is used to update only the user that contains that Id.
  • For DELETE we only need the Id of the user that we want to delete.

Controller 🛠

We will request data from the UI by triggering methods defined in the controller. And then controller will take rest of the responsibilities.

As I have said, the UserApi class only returns RAW data. Within the controller class, the RAW data is converted into the UserModel .

GetxController comes with onInit() and onClose() methods. This allows us to completely avoid using StatefulWidget and write organised code.

Create a home_controller.dart file inside lib > app> module > home > controller then paste the below code.

State Mixin 🦾

Another way to handle ourUI state is use the StateMixin<T> . To implement it, use the with to add the StateMixin<T> to your controller which allows a T model.

The change() method of StateMixin changes the State whenever we want. We just have to pass the data and the status.

class HomeController extends GetxController with StateMixin<List<User>>

visit GetxStateMixin for more info ℹ️

Error Handling ⚠️

If you see the above controller I’ve used ApiException class for catching the DioError.

I just made a different class that returns the error message in human-readable form. The server error, the cancel request error, or the connection timeout message could all be the cause.

This class is very handy when you are handling errors.

Head over to lib > data > network > serviveand create api_exception.dart class.

📍 Now you just need to pass DioError inside the fromDioError method and it will return a relavent message

final ApiException apiException = ApiException.fromDioError(e);

Bindings 🔗

To avoid declaring our dependencies in the view class, we can separate them from the view using Bindings.

To do this create a Class and extend it with Bindings. Then there is an override method void dependencies() which will hold the dependencies.

Bindings are classes where we can declare our dependencies and then ‘bind’ them to the routes.

Building UI 📱

List of users from API

As you can see, the HomeView contains list of users. We will use controller.obx()in order to display users, When the server successfully returns a data otherwise we will show an error.

Create a home_view.dart file inside lib > app > module > home > view and paste the code below.

Application Flow ⏳

When you first launch the app, the controller will call the fetchUsers() method to get the list of users from the API. The response will be parsed into a UserModel object and then assigned to the users variable. The users variable is an RxList, so it will automatically update the UI when the data changes.

The change() method is used to update the state of the controller. The change() method takes two parameters: the data and the status. The status can be RxStatus.success(), RxStatus.error(), or RxStatus.loading(). The status will be used to display the appropriate UI.

Wrapping Up 🤩

I hope this article has helped you understand how to use the GetX library to manage the state of your Flutter app. If you have any questions or suggestions, please leave a comment below. 😍 Thanks for reading :-)

Source Code 👨🏻‍💻

--

--