👋
Flutterのdioについて
Flutter の dio という、HTTP 通信を行う際に使用するライブラリを使用する機会があったので、その時に調べた内容をまとめました。
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,
}
参考
Discussion