# Flutter API 通信 Dio の基本
Dio とは
- イタリア語 Dìo は(キリスト教の)神、天主、創造主、造物主の意味します。コトバンク Dio (opens new window)
- 本田バイクにも Dio という 50cc スクーターがあります。ギリシア神話に登場する「全知全能の神」ゼウスの息子たち「Dioskuroi(ディオスクーロイ)」からの造語だそうです。Dio の名前の由来を教えて (opens new window)
- ディスク入出力(Disc Input / Output)の略でも DIO 使っています。Digital Input / Output も同じく
Dio についていろいろ意味があるようですが、Flutter の Dio はイタリア語の神という意味かなと思います。
# Dio の特徴
- レスポンスの自動変換できる
- インターセプター、グローバル設定ができる
- connectTimeout receiveTimeout sendTimeout のタイムアウト設定ができる
- ファイルアップロード/ダウンロード
- リクエストのリトライができる
- リクエストのキャンセルができる
- 多言語サポート
- クッキー、キャッシュを管理できるプラグインがある
Flutter Dio Package (opens new window)
Dio Plugins Topic (opens new window)
# Dio の基本
// api_service.dart
import 'dart:convert';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:dio/dio.dart';
class ApiService {
final _dio = Dio(BaseOptions(
baseUrl: dotenv.env['API_BASE_URL'] ?? '',
connectTimeout: const Duration(seconds: 5), // 5秒
receiveTimeout: const Duration(seconds: 3), // 3秒
headers: {'Content-Type': 'application/json'},
));
Future<dynamic> get(String endpoint) async {
try {
final response = await _dio.get(endpoint);
return response.data;
} on DioException catch (e) {
throw Exception('Failed to load data: ${e.response?.statusCode}');
}
}
Future<dynamic> post(String endpoint, Map<String, dynamic> data) async {
try {
final response = await _dio.post(
endpoint,
data: jsonEncode(data),
);
return response.data;
} on DioException catch (e) {
throw Exception('Failed to post data: ${e.response?.statusCode}');
}
}
Future<dynamic> put(String endpoint, Map<String, dynamic> data) async {
try {
final response = await _dio.put(
endpoint,
data: jsonEncode(data),
);
return response.data;
} on DioException catch (e) {
throw Exception('Failed to update data: ${e.response?.statusCode}');
}
}
Future<dynamic> delete(String endpoint) async {
try {
final response = await _dio.delete(endpoint);
return response.data;
} on DioException catch (e) {
throw Exception('Failed to delete data: ${e.response?.statusCode}');
}
}
}
// user_service.dart
import 'package:my_app/models/user.dart';
import 'api_service.dart';
class UserService {
final ApiService apiService;
UserService({required this.apiService});
Future<List<User>> fetchUsers() async {
final data = await apiService.get('/users');
return data.map<User>((json) => User.fromJson(json)).toList();
}
Future<User> updateUser(int id, Map<String, dynamic> data) async {
final response = await apiService.put('/users/$id', data);
return User.fromJson(response);
}
Future<dynamic> deleteUser(int id) async {
final response = await apiService.delete('/users/$id');
return response;
}
}
Javascript の Axios パッケージと似ている使い方で、Axios 経験者なら取り扱いやすいですね。
# Dio のインターセプター
リクエストとレスポンスのインターセプター
import 'package:dio/dio.dart';
void main() async {
Dio dio = Dio();
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
print('Request: ${options.method} ${options.path}');
return handler.next(options); // リクエストを続行
},
onResponse: (response, handler) {
print('Response: ${response.statusCode} ${response.data}');
return handler.next(response); // レスポンスを続行
},
onError: (DioError e, handler) {
print('Error: ${e.message}');
return handler.next(e); // エラーを続行
},
));
try {
Response response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
print(response.data);
} catch (e) {
print(e);
}
}
# Dio のリクエストのキャンセル
import 'package:dio/dio.dart';
void main() async {
Dio dio = Dio();
CancelToken cancelToken = CancelToken();
// リクエストの実行
dio.get(
'https://jsonplaceholder.typicode.com/posts/1',
cancelToken: cancelToken,
).catchError((e) {
if (CancelToken.isCancel(e)) {
print('Request canceled: ${e.message}');
} else {
print('Error: ${e.message}');
}
});
// リクエストのキャンセル
cancelToken.cancel('Request canceled by user.');
}