Flutter Dio Complete Guide

Flutter Dio Complete Guide

    Flutter networking could be done using Dio package. Dio package provides many convenient methods for http network request and handling response. The official document says

    A powerful HTTP client for Dart/Flutter, which supports global configuration, interceptors, FormData, request cancellation, file uploading/downloading, timeout, and custom adapters etc.

    In my project chat app I have used all the features and here I will explain some of the core functionalities of the package.

    Install & Example

    Make sure you have installed the package using the command below

    flutter pub add dio

    Very simple example of it

    import 'package:dio/dio.dart';
    
    /// More examples see https://github.com/cfug/dio/blob/main/example
    void main() async {
      final dio = Dio();
      final response = await dio.get('https://pub.dev');
      print(response.data);
    }

    Wrapper class

    Just like http.get request of http package, Dio http works the same way. We will create a special class, this class would contain all of the Dio methods and other helper function.

    We will call this class HttpUtil, and it would be a Singleton class. Singleton class it means we will only create one instance of this.

    class HttpUtil {
      static final HttpUtil _instance = HttpUtil._internal();
      factory HttpUtil() => _instance;
    
    }

    This Singleton class would contain all of our Dio methods.

    Init Dio

    Let's create a new Dio instance inside the class as a late variable.

     late Dio dio;

    This variable dio, we will assign an instance later once we are done with BaseOptions.

    BaseOptions

    We also have to set BaseOptions contructor using various parameters like

    1. baseUrl
    2. connectionTimeout
    3. receiveTimeout
    4. headers
    5. contentType
    6. responseType
     BaseOptions options = BaseOptions(
    
          baseUrl: SERVER_API_URL,
    
          connectTimeout: 30000,
    
          receiveTimeout: 5000,
    
          headers: {},
    
          contentType: 'application/json; charset=utf-8',
    
          responseType: ResponseType.json,
        );

    Make sure you set up SERVER_API_URL correctly. 

    After that actually we are ready to use Dio methods like get() and post(). Let's see the class.

    class HttpUtil {
      static final HttpUtil _instance = HttpUtil._internal();
      factory HttpUtil() => _instance;
    
      late Dio dio;
    
      HttpUtil._internal() {
        BaseOptions options = BaseOptions(
    
          baseUrl: SERVER_API_URL,
    
          connectTimeout: 30000,
    
          receiveTimeout: 5000,
    
          headers: {},
    
          contentType: 'application/json; charset=utf-8',
    
          responseType: ResponseType.json,
        );
    
        dio = Dio(options);

    dio get()

    After that, we can set up our http get() method. For Dio package users we will see dio.get() for get() request. 

        var response = await dio.get(
          path,
          queryParameters: queryParameters,
          options: options,
          cancelToken: cancelToken,
        );
        return response.data;

    After that, we return a response. It's a JSON response. It's upto you how much you information you return from your sever side. Look at my server side repsonse

     return ["code"=>0, 'data'=>$res, "msg"=>"got all the users info"];

    Here you see, I return many fields in the JSON reponse. But my data field only contains the result you want. You may return as many fields as you want. 

    And use the response in your front end Flutter app. 

    Inside dio.get() method, only path parameter is the compulsory one. Others are optional.  We may use a wrapper for dio.get() , that wrapper would help you with the optional parameters.

      Future get(
        String path, {
        Map<String, dynamic>? queryParameters,
        Options? options,
        bool refresh = false,
        bool noCache = !CACHE_ENABLE,
        bool list = false,
        String cacheKey = '',
        bool cacheDisk = false,
      }) async {
        Options requestOptions = options ?? Options();
        requestOptions.extra ??= Map();
        requestOptions.extra!.addAll({
          "refresh": refresh,
          "noCache": noCache,
          "list": list,
          "cacheKey": cacheKey,
          "cacheDisk": cacheDisk,
        });
    
        var response = await dio.get(
          path,
          queryParameters: queryParameters,
          options: options,
          cancelToken: cancelToken,
        );
        return response.data;
      }

    From your UI, you may call HttpUtil().get() with required parameter path, if you don't know what else to send, skip others.

    dio.post()

    The post method of Dio is more like dio.get(). Everything else stays the same, but we need to provide headers info and data to send to the server.

    Most of the post method requires sending special kind of token to send to server. We will send that in a header. First let's work on method that would find the token from the local device and then return that header. The returned header we will use in dio.post() method.

      Map<String, dynamic>? getAuthorizationHeader() {
        var headers = <String, dynamic>{};
        if (Get.isRegistered<UserStore>() && UserStore.to.hasToken == true) {
          headers['Authorization'] = 'Bearer ${UserStore.to.token}';
        }
        return headers;
      }

    Here in the method we see that we have a condition and in this we use UserStore.to.hasToken to check if the device has saved any token or not. 

    If there's a token then we save in headers map and return the map.

    We also need to send data to server. dio.post() takes dynamic data type that means we can send Map data to the post method.

     var response = await dio.post(
          path,
          data: data,
          queryParameters: queryParameters,
          options: requestOptions,
          cancelToken: cancelToken,
        );

    Now let's the the complete post method

      Future post(
        String path, {
        dynamic data,
        Map<String, dynamic>? queryParameters,
        Options? options,
      }) async {
    
        Options requestOptions = options ?? Options();
        requestOptions.headers = requestOptions.headers ?? {};
        Map<String, dynamic>? authorization = getAuthorizationHeader();
        if (authorization != null) {
          requestOptions.headers!.addAll(authorization);
        }
        var response = await dio.post(
          path,
          data: data,
          queryParameters: queryParameters,
          options: requestOptions,
          cancelToken: cancelToken,
        );
    
        return response.data;
      }

    ..........coming more..........

    Recent posts