# Flutter 好用package - dio 介紹
## dio
處理 http 請求用套件,相較於 Dart 團隊製作的 `http` 套件,個人覺得更好用些~
```
flutter pub add dio
```
[官網](https://pub.dev/packages/dio)
### pretty_dio_logger
dio 相關的漂亮 log 套件
```
flutter pub add pretty_dio_logger
```
### 程式範例
network/api_service.dart
```dart!
Dio networkServiceDio({required String baseUrl}) {
var dio = Dio(
BaseOptions(
connectTimeout: ServicesConfig.connectTimeout,
receiveTimeout: ServicesConfig.receiveTimeout,
baseUrl: baseUrl,
responseType: ResponseType.json,
),
);
//攔截器
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {
//統一添加 header
options.headers['Authorization'] =
'Bearer ${LocalStorage.get('token')}';
options.headers['content-type'] = 'application/json';
handler.next(options);
},
onResponse: (Response response, handler) {
if (response.statusCode != 200) {
//若狀態碼不等於200不處理request
return handler.reject(
DioError(
requestOptions: response.requestOptions,
response: response,
type: DioErrorType.other,
error: response.statusMessage,
),
);
}
//繼續處理
return handler.next(response);
},
onError: (DioError e, handler) async {
//token 驗證失敗重新請求 token 後繼續處理
if (e.response != null && e.response!.statusCode == 401) {
var result = await ApiService().refreshToken();
if (result) {
return handler.resolve(await ApiService().retry(e.requestOptions));
}
} else {
return handler.next(e);
}
},
),
);
//漂亮的log,需額外裝套件
dio.interceptors
.add(PrettyDioLogger(logPrint: (o) => debugPrint(o.toString())));
return dio;
}
class ApiService {
static final Dio _dio1 = networkServiceDio(baseUrl: ServicesConfig.baseUrl1);
static final Dio _dio2 =
networkServiceDio(baseUrl: ServicesConfig.baseUrl2);
//多個baseUrl 進行切換
static Dio switchBaseUrl(type) {
switch (type){
case 1:
return _dio1;
case 2:
return _dio2;
}
}
//更新token後重新請求
Future<Response<dynamic>> retry(RequestOptions requestOptions) async {
Options options = Options(
method: requestOptions.method,
headers: {
'Authorization': 'Bearer ${LocalStorage.get('token')}',
'content-type': 'application/json'
},
);
return switchBaseUrl(1).request<dynamic>(requestOptions.path,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters,
options: options);
}
//回應401後重新取得token
Future<bool> refreshToken() async {
Response response = await switchBaseUrl(1).post('/refreshToken', data: {
'accessToken': '原始token',
'refreshToken': '原始refreshToken',
});
if (response.statusCode == 200) {
//取得最新 token
RefreshToken model = RefreshToken.fromJson(response.data);
await LocalStorage.set('token', model.accessToken);
await LocalStorage.set('refreshToken', model.refreshToken);
return true;
}
return false;
}
//get範例
static Future<Contact> getExampleList() async {
final response = await switchBaseUrl(1)
.get('/exampleList', queryParameters: {'type': 'cat'});
Contact model = Contact.fromJson(response.data);
return model;
}
}
```
###### tags: `flutter`