Flutter Dio http簡單封裝與使用

自心 發表於 2020-09-23


初次封裝版本,後續更新完善。不足的地方歡迎提供意見,非常樂意學習請教。

dio簡單封裝

import 'dart:convert';
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:yunxiaobao/utils/shared_util.dart';
import '../config/dio_config.dart';

/// dio統一封裝
/// xxx 2020-09-21 add
class DioUtil {
  /// 例項
  static DioUtil _instance;

  /// token字首
  static const String _refreshTokenKey = 'Admin-Refresh-Token';

  /// token字首2
  static const String _accessTokenKey = "Bearer ";

  /// 獲取例項
  static DioUtil getInstance() {
    if (_instance == null) _instance = DioUtil();
    return _instance;
  }

  /// 預設配置
  Dio dio = Dio();
  DioUtil() {
    // 請求地址
    dio.options.baseUrl = DioConfig.baseUrl;
    // 超時時間
    dio.options.connectTimeout = 5000;
    // 接受資料超時時間
    dio.options.receiveTimeout = 3000;
    // 列印日誌
    dio.interceptors.add(LogInterceptor(responseBody: DioConfig.isDebug));
    // SSL證照策略
    noSSl();
  }

  /// get請求方法
  get(String url,
      {Map<String, dynamic> params, Function success, Function error}) {
    _requestHttp(url, success, 'get', params, error);
  }

  /// post請求方法
  post(String url,
      {Map<String, dynamic> params, Function success, Function error}) {
    _requestHttp(url, success, 'post', params, error);
  }

  // 請求
  _requestHttp(String url, Function successCallBack,
      [String method,
      Map<String, dynamic> params,
      Function errorCallBack]) async {
    // 從本地快取拿到兩個token
    String accessToken = await SharedUtil.getValue('access_tokenKey');
    String refreshToken = await SharedUtil.getValue('refresh_token');
    // 設定頭
    dio.options.headers = {
      "authorization": _accessTokenKey + accessToken,
      "Cookie": _refreshTokenKey + refreshToken,
    };
    Response response;

    /// 發起請求
    try {
      // get請求
      if (method == 'get') {
        if (params != null && params.isNotEmpty) {
          response = await dio.get(url, queryParameters: params);
        } else {
          response = await dio.get(url);
        }
      }
      // post請求
      else if (method == 'post') {
        if (params != null && params.isNotEmpty) {
          response = await dio.post(url, data: params);
        } else {
          response = await dio.post(url);
        }
      }
    }

    /// 請求錯誤處理
    on DioError catch (error) {
      // 錯誤型別
      String msg = error.message;
      if (error.type == DioErrorType.CANCEL)
        msg = "連線被取消";
      else if (error.type == DioErrorType.CONNECT_TIMEOUT)
        msg = "請求時超時";
      else if (error.type == DioErrorType.SEND_TIMEOUT)
        msg = "連線超時";
      else if (error.type == DioErrorType.RECEIVE_TIMEOUT) msg = "接收超時";
      if (errorCallBack != null) _error(errorCallBack, msg);
      return;
    }

    /// 根據伺服器響應結果進行處理(可根據返回狀態碼處理)
    // String strData = json.encode(response.data['data']); // 轉json字串
    // Map<String, dynamic> dataMap = json.decode(strData); // 轉map(json)
    Map<String, dynamic> dataMap = response.data;
    if (dataMap == null || dataMap['code'] == null)
      _error(errorCallBack, "返回引數異常");
    else if (dataMap['code'] == 401)
      _error(errorCallBack, "沒有許可權");
    else
      successCallBack(dataMap);
  }

  // 是否忽略SSL證照
  noSSl() {
    if (DioConfig.noSSL)
      (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
          (client) {
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) {
          return true;
        };
      };
  }

  // 錯誤處理
  _error(Function errorCallBack, String msg) {
    errorCallBack(msg);
  }
}

配置類

/// 請求統一請求的配置
/// xxx 2020-09-23 add
class DioConfig {
  /// 是否列印請求日誌
  static const bool isDebug = false;

  /// 忽略證照
  static const bool noSSL = true;

  /// 請求地址
  static const String baseUrl = "https://easy-mock.com";
}

介面地址類

/// 測試相關介面
/// xxx 2020-09-23 add
class TestApi {
  /// 測試介面1
  static String test = "/mock/5f6b573cb766f82502c8a3b2/api/test";

  /// 測試介面2
  static String test2 = "/mock/5f6b573cb766f82502c8a3b2/api/test2";

  /// 測試介面2
  static String test3 = "/mock/5f6b573cb766f82502c8a3b2/api/test3";
}

本地快取讀取工具類

import 'package:shared_preferences/shared_preferences.dart';

/// 本地儲存工具類
/// xxx 2020-09-23 add
class SharedUtil {
  /// 根據Key取值
  static getValue(String key) async {
    SharedPreferences sp = await SharedPreferences.getInstance();
    String value = sp.get(key);
    if (value == null) return "";
    return value;
  }

  /// 根據key設定值
  static setValue(String key, String value) async {
    SharedPreferences sp = await SharedPreferences.getInstance();
    sp.setString(key, value);
  }
}

簡單使用

  /// 測試
  // 方法
  _loginBtn() async {
    // 呼叫方法
    DioUtil.getInstance().get(
      TestApi.test3,
      success: (data) {
      	// 成功返回結果
        print(data);
      },
      error: (error) {
      	// 失敗返回結果
        print('失敗' + error);
      },
    );
  }

使用相關包

dio: ^3.0.10
shared_preferences: 0.5.10