# 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`