What is Dio in Flutter? Best Practices to Handle Networking in Flutter

what is dio in Flutter

During application development, managing the network requests could be one of the hectic tasks for you. If you managed the network requests efficiently, your app is likely going to succeed in the market. Responses returned by a network may contain unexpected results, and in order to have a better user experience, you need to take care of such snags in advance. In this article, we are going to get familiar with Dio in Flutter.

When you start working on a large application, you need to do something more advanced. Your application will face lots of problems with network handling. In that case, we need some advanced connection library that has extra features like interceptors, logs, cache, etc. that will be helpful in many tasks like adding the token authentication for each request and logging requests.

In this article, we’re going to learn about Dio and have a look at the best practices for handling networking in Flutter.

What is Dio in Flutter?

Dio is a powerful HTTP client for Dart. It supports interceptors, global configuration, FormData, request cancellation, file downloading, and timeout, among others. Flutter offers an HTTP package that’s good for performing basic network tasks but is pretty intimidating to use when handling some advanced features.

If we compare the HTTP package with Dio, Dio provides an intuitive API for performing advanced networking tasks with minimal effort. The normal HTTP library can do the things which dio does and we get it in flutter SDK too. But it’s not that easy to learn or understand the http library so dio would be better.

Get Started with Dio

To get started with Dio, we first need to add dependencies.

dependencies:
dio: ^3.0.8

Then install the package using the command line in your terminal and import it:

To install the package:  flutter pub get Or pub get

Now use this in your dart code: import ‘package:dio/dio.dart’;

GET Request

To use methods of the Dio HTTP client, we have to create an instance of the Dio client. After that, we can call all methods of Dio. As you can see in the code below, we have created an instance of Dio to call GET requests.

Future<dynamic> getData() async {

    try {

      Response response;

      var dio = Dio();

      /// apiUrl is basically the route from where you get data

      response = await dio.get(‘$apiUrl/persons’);

      debugPrint(response.data.toString());

    } catch (_) {

      rethrow;

    }

  }

POST Request

The instance of Dio provides a POST method by which we can pass param in JSON format. After getting the request using the Dio instance, await for the request you want to post.

Future postData() async {

    try {

      Response response;

      var dio = Dio();

      /// apiUrl is basically the route from where you get data

      response = await dio.post(‘$apiUrl/persons’, data: {

        ‘name’: ‘xyz’,

        ‘age’: ’22’,

        ‘gender’: ‘Male’,

      });

      debugPrint(response.data.toString());

    } catch (_) {

      rethrow;

    }

  }

Multiple Concurrent Requests

When you need to call different APIs in the same instance of time it tends to get confusing a lot. At that time, we can use dio to get the responses from different APIs.

Future multipleConcurrentRequests() async {

    var dio = Dio();

    try {

      List<Response> response = await Future.wait(

        [

          dio.post(‘$apiUrl/persons’),

          dio.get(‘/token’),

        ],

      );

    } catch (_) {

      rethrow;

    }

  }

To Download a File from Server

To download a file from the server, Dio provides a download method. In this method, we have to pass the complete path of the file.

Future downloadingFile() async {

    Response response;

    var dio = Dio();

    try {

      response = await dio.download(‘https://www.google.com/’, ‘./xx.html’);

      return response.data;

    } catch (_) {

      rethrow;

    }

  }

Get Response Stream

With the help of stream response, we can receive a sequence of events. To get a response stream with the Dio client, we need to set responseType stream.

Future responseStream() async {

    try {

      Response<ResponseBody> responseBody;

      responseBody = await Dio().get<ResponseBody>(

        /// apiUrl is basically your url

        apiUrl,

        options: Options(

          responseType: ResponseType.stream,

        ),

      );

    } catch (_) {

      rethrow;

    }  

}

Get Response with Bytes

To get a response in bytes, we have to set responseType to ‘bytes’. As you can see:

Future responseBtyes() async {

    try {

      Response<List<int>> response;

      response = await Dio().get<List<int>>(

        /// apiUrl is basically your url

        apiUrl,

        options: Options(responseType: ResponseType.bytes),

      );

    } catch (_) {

      rethrow;

    }

  }

Send FormData

To send the FormData, we use the instance FormData from the map and specify where we want to send the data and wait for the post.

Future sendingFormData() async {

    var dio = Dio();

    try {

      var formData = FormData.fromMap({

        ‘name’: ‘xyz’,

        ‘age’: 25,

      });

      /// apiUrl is basically your url

      await dio.post(apiUrl, data: formData);

    } catch (_) {

      rethrow;

    }

  }

Upload Multiple Files to Server by FormData

When you need to upload multiple files to the server by your formData, at that time you can use MultiPartFile. And then awaiting for it step by step and vice versa can reduce your valuable time. Additionally, we can pass the required param with the same request.

Future uploadingMultipleFiles(File file) async {

    var dio = Dio();

    try {

      var formData = FormData.fromMap(

        {

          ‘name’: ‘xyz’,

          ‘age’: 25,

          ‘file’: await MultipartFile.fromFile(

            file.path,

            filename: ‘upload.txt’,

          ),

          ‘files’: [

            await MultipartFile.fromFile(‘./text1.txt’, filename: ‘text1.txt’),

            await MultipartFile.fromFile(‘./text2.txt’, filename: ‘text2.txt’),

          ]

        },

      );

      /// apiUrl is basically your url

      var response = await dio.post(apiUrl, data: formData);

      return response;

    } catch (_) {

      rethrow;

    }

  }

It is a must to mention that the request initiated by HttpClient is still used internally by dio, so the proxy, request authentication, certificate verification, etc. are the same as HttpClient, and we can onHttpClientCreateset it in the callback.

Listening the Uploading Progress

Sometimes, we need to listen the uploading progress of the response after using await in the post request. The dart dio provides onSendProgress function to listen the uploading progress.

Future uploadingProgress() async {

    var dio = Dio();

    Response response;

    try {

      response = await dio.post(

        /// apiUrl is basically your url

        apiUrl,

        data: {‘aa’: ‘bb’ * 22},

        onSendProgress: (int sent, int total) {

          debugPrint(‘$sent $total’);

        },

      );

      return response;

    } catch (_) {

      rethrow;

    }

  }

Post Binary Data by Stream

Future binaryDataByStream() async {

    var dio = Dio();

    try {

      /// Binary data

      List<int> postData = <int>[];

      await dio.post(

        apiUrl,

        data: Stream.fromIterable(postData.map((e) => [e])),

        ///create a Stream<List<int>>

        options: Options(

          headers: {

            /// set content-length

            Headers.contentLengthHeader: postData.length,

          },

        ),

      );

    } catch (_) {

      rethrow;

    }

  }

There are a lot of other features that Dio provides from dio API.

Some of these are as follows:

baseUrl: It requests the base URL which normally contains the sub path. Like “https://www.google.com/api/”.

connectionTimeout: It contains the timeout in milliseconds for opening URL.

receiveTimeout: Whenever the time between two events from the response stream is greater than receiveTimeout then the Dio will throw the DioError with DioErrorType.RECEIVE_TIMEOUT .

For each dio instance, we can add one or more interceptors, by which we can intercept requests or responses before they are handled by then or catchError. If you want to resolve and reject the request you can return a Response object or return dio.resolve(data). If you want to lock/unlock the interceptors you can use the lock()/unlock() method.

Conclusion

I hope you find this article useful. As you can see Dio contains lots of customizable features like adding Cache Retry, Connection time out, and different interceptors. We can also include logs. Dio in Flutter can be very useful in cases where you need features like offline cache etc.

Still have any question? Leave a comment below with your queries or suggestions (if you have any). FlutterDesk is always there to help flutter enthusiasts excel in their app development expertise.

Leave a Comment

Your email address will not be published.

Translate »