👋

Flutterのdioについて

2025/01/09に公開

Flutter の dio という、HTTP 通信を行う際に使用するライブラリを使用する機会があったので、その時に調べた内容をまとめました。

https://pub.dev/packages/dio

dio

dio は Intercepter を使って、リトライ処理を書けたり、リクエストやレスポンス、エラー処理をする前に処理を加えることができます。
http を使って実装するよりも、コードの記述量が抑えられて、スッキリ書けるのが特徴です。

セットアップ

公式を見てみると、以下のような記述があり、プロジェクトで実際に使用する際には、Dio のシングルトンを使った方が良いらしい。

It is recommended to use a singleton of Dio in projects, which can manage configurations like headers, base urls, and timeouts consistently. Here is an example that use a singleton in Flutter.

タイムアウトの設定や、ベース URL の設定は下記のように行う。(2 つのパターンがあり、どちらでも OK のよう)

final dio = Dio();

void configureDio() {
  // Set default configs
  dio.options.baseUrl = 'https://api.pub.dev';
  dio.options.connectTimeout = Duration(seconds: 5);
  dio.options.receiveTimeout = Duration(seconds: 3);

  // Or create `Dio` with a `BaseOptions` instance.
  final options = BaseOptions(
    baseUrl: 'https://api.pub.dev',
    connectTimeout: Duration(seconds: 5),
    receiveTimeout: Duration(seconds: 3),
  );
  final anotherDio = Dio(options);
}

BaseOptionsには以下のプロパティが含まれており、それぞれ設定することができる。

  • method : HTTP メソッド
  • connectTimeout : 接続時間のタイムアウト
  • receiveTimeout : データ受取のタイムアウト
  • sendTimeout : データ送信時のタイムアウト
  • baseUrl : ベース URL
  • queryParameters : パラメータ
  • extra : Interceptor・Transformer で取得できる追加マップ
  • headers : HTTP リクエストヘッダー
  • preserveHeaderCase : ヘッダーキーの大文字と小文字を区別するかどうか
  • responseType : json、stream、plain、bytes の 4 種類があり、デフォルトは json
  • contentType : リクエストのコンテンツタイプ
  • validateStatus : ステータスコード
  • receiveDataWhenStatusError : リクエストが失敗した場合にもデータを受け取るかどうか(デフォルトは true)
  • followRedirects : 詳しくはこちら
  • maxRedirects : followRedirects が true の場合に、最高で何回リダイレクトするか
  • persistentConnection : 詳しくはこちら
  • requestEncoder : リクエストをエンコードするメソッドを設定
  • responseDecoder : レスポンスをデコードするメソッドを設定
  • listFormat : リクエストパラメータのフォーマット
BaseOptions({
    super.method,
    Duration? connectTimeout,
    super.receiveTimeout,
    super.sendTimeout,
    String baseUrl = '',
    Map<String, dynamic>? queryParameters,
    super.extra,
    super.headers,
    super.preserveHeaderCase = false,
    super.responseType = ResponseType.json,
    super.contentType,
    super.validateStatus,
    super.receiveDataWhenStatusError,
    super.followRedirects,
    super.maxRedirects,
    super.persistentConnection,
    super.requestEncoder,
    super.responseDecoder,
    super.listFormat,
  })

使い方

一番シンプルに使うとしたら、以下のような形で使うことになる。

import 'package:dio/dio.dart';

final dio = Dio();

// GET
void getHttp() async {
  Response response;
  response = await dio.get('/test?id=12&name=dio');
  // 別の方法だと以下のようにしてリクエストを行う
  response = await dio.get(
    '/test',
    queryParameters: { 'id': 12, 'name' 'dio' },
  );
}

// POST
void postHttp() async {
    final response = await dio.post(
        '/test',
        data: { 'id': 12, 'name' 'dio' },
    );
}

複数のリクエストを同時に行う場合は以下のようにして、複数のリクエストを待つという感じ。

response = await Future.wait([dio.post('/info'), dio.get('/token')]);

Interceptors

dio は、Interceptors を追加することができるので、リクエストやレスポンス、エラー処理をする前に処理を加えることができます。
ログを出力する時などにも使えそうです。

import 'package:dio/dio.dart';

class CustomInterceptors extends Interceptor {
  
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    print('REQUEST[${options.method}] => PATH: ${options.path}');
    super.onRequest(options, handler);
  }

  
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    print('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
    super.onResponse(response, handler);
  }

  
  Future onError(DioException err, ErrorInterceptorHandler handler) async {
    print('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
    super.onError(err, handler);
  }
}

エラー処理

DioException でラップされて処理されます。

DioException({
  required this.requestOptions,
  this.response,
  this.type = DioExceptionType.unknown,
  this.error,
  StackTrace? stackTrace,
  this.message,
})

enum DioExceptionType {
  connectionTimeout,

  sendTimeout,

  receiveTimeout,

  badCertificate,

  badResponse,

  cancel,

  connectionError,

  unknown,
}

参考

https://medium.com/@vikranthsalian/flutter-dio-vs-http-1dc1d4f95fda
https://pub.dev/packages/dio

Discussion