flutter对dio的优雅封装

 

1.准备工作,相关内容

flutter dio 封装(增加 loading dialog)

flutter dio 封装(log 打印)

flutter dio封装(返回值泛型的处理)

2.目录结构

flutter对dio的优雅封装_第1张图片

3.代码片段

这边只列举 get 和 post 方法

1).GET方法

get(String url,
      {HttpCallBack success,
      HttpCallBack special,
      HttpCallBack error,
      bool hasLoading,
      BuildContext context}) async {
    _http(HttpMethod.GET, url, null,
        success: success,
        special: special,
        error: error,
        hasLoading: hasLoading,
        context: context);
  }

 2).Post方法

post(String url, Map map,
      {HttpCallBack success,
      HttpCallBack special,
      HttpCallBack error,
      bool hasLoading,
      BuildContext context}) async {
    _http(HttpMethod.POST, url, map,
        success: success,
        special: special,
        error: error,
        hasLoading: hasLoading,
        context: context);
  }

这边使用泛型来代替参数:

T 表示返回的是否是集合,有HttpResponseEntity和HttpResponseListEntity两种

G 表示返回的是接口返回的类型(即你需要的类型)

这两个点后面会代码展示,先看_http 方法

_http(HttpMethod method, String url, Map map,
      {HttpCallBack success,
      HttpCallBack special,
      HttpCallBack error,
      bool hasLoading,
      BuildContext context}) async {
    this.context = context;
    var header = await getHeader();
    _options = BaseOptions(
        connectTimeout: HttpConfig.connectTimeout,
        receiveTimeout: HttpConfig.receiveTimeout,
        baseUrl: HttpConfig.baseUrl,
        headers: {
          SharedPreConfig.TOKEN: header[SharedPreConfig.TOKEN],
          SharedPreConfig.LOCATION: header[SharedPreConfig.LOCATION],
          SharedPreConfig.UUID: header[SharedPreConfig.UUID],
          SharedPreConfig.USER_AGENT: header[SharedPreConfig.USER_AGENT],
          SharedPreConfig.NET_STATE: header[SharedPreConfig.NET_STATE]
        });
    _dio = Dio(_options);
    _dio.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) {
      print(
          "\n================================= 请求数据 =================================");
      print("method = ${options.method.toString()}");
      print("url = ${options.uri.toString()}");
      print("headers = ${options.headers}");
      print("params = ${options.queryParameters}");
    }, onResponse: (Response response) {
      print(
          "\n================================= 响应数据开始 =================================");
      print("code = ${response.statusCode}");
      print("data = ${response.data}");
      print(
          "================================= 响应数据结束 =================================\n");
    }, onError: (DioError e) {
      print(
          "\n=================================错误响应数据 =================================");
      print("type = ${e.type}");
      print("message = ${e.message}");
      print("stackTrace = ${e.stackTrace}");
      print("\n");
    }));

    if (hasLoading != null && context != null) {
      this.hasLoading = hasLoading;
    } else {
      this.hasLoading = false;
    }
    showLoadingDialog();
    try {
      Response response = await _getResponse(method, url, map);
      hiddeLoadingDialog();
      if (response.statusCode == 200) {
        if (response.data['Flag'] == 100) {
          _httpSuccess(response.data, success);
        } else {
          _httpSpecial(response.data, special);
        }
      } else {
        _httpError("网络状况不佳", error);
      }
    } catch (e) {
      _httpError(e.toString(), error);
    }
  }

要显示 dialog 必须传入 context,并且 hasLoading 为 ture

主要的看下getResponse(),和回调方法

getResponse()方法:

 _getResponse(HttpMethod method, String url, Map map) async {
    Response response;
    switch (method) {
      case HttpMethod.GET:
        response = await _dio.get(url);
        return response;
      case HttpMethod.POST:
        response = await _dio.post(url, queryParameters: map);
        return response;
      case HttpMethod.PATCH:
        response = await _dio.patch(url, queryParameters: map);
        return response;
      case HttpMethod.DELETE:
        response = await _dio.delete(url, queryParameters: map);
        return response;
      case HttpMethod.PUT:
        response = await _dio.put(url, queryParameters: map);
        return response;
      default:
        response = await _dio.get(url);
        return response;
    }
  }

通过getResponse 方法获得了 Response,然后对 response 进行处理

定义回调方法

typedef HttpCallBack

= dynamic Function(P response);

response.statusCode==200为 ture 则请求接口成功

例如我这的接口返回格式是{"Flag": 100,"FlagString": "\u8bf7\u6c42\u6210\u529f","data": []}

_httpSuccess():处理成功回调

 ///statusCode==200&&Flag==100
  _httpSuccess(Map response, HttpCallBack success) {
    if (success != null) {
      if (T.toString() == "HttpResponseEntity") {
        success((HttpResponseEntity.fromJson(response).data));
      } else if (T.toString() == "HttpResponseListEntity") {
        success(HttpResponseListEntity.fromJson(response).data);
      } else {
        success(response['FlagString']);
      }
    }
  }

可以看出,当 T 为HttpResponseEntity时,会返回 G,当 T为 HttpResponseListEntity 时,会返回 List;当 T不传时,表示不处理 data,只返回Flag信息。如何实现的具体请看上面的泛型链接。

如何调用?

代码示例:

 void _getHomeList(int currentPage) async {
    await HttpUtil.getInstance().get(
        '${HttpUrl.HOME_PAGE_URL}name=circle&page=${_currentPage}&sort=0',
        success: (response) {
      setState(() {
        _homeList.addAll(response);
      });
    });
  }

后续:

代码只是初步封装,后续会进一步完善。

贴下主要代码


import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:percentage_flutter/config/SharedPreConfig.dart';
import 'package:percentage_flutter/widget/dialog/loading_dialog.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'http_config.dart';
import 'http_flag_code.dart';
import 'dart:convert';

import 'http_response_entity.dart';

typedef HttpCallBack

= dynamic Function(P response); enum HttpMethod { GET, POST, DELETE, PUT, PATCH } ///http 工具类 class HttpUtil { HttpMethod method; BaseOptions _options; Dio _dio; bool hasLoading; BuildContext context; static HttpUtil _instance; static HttpUtil getInstance() { if (_instance == null) { _instance = HttpUtil(); } return _instance; } ///获取头部信息 dynamic getHeader() async { SharedPreferences prefs = await SharedPreferences.getInstance(); String headerData = prefs.get(SharedPreConfig.NET_HEADER_DATA); return json.decode(headerData); } get(String url, {HttpCallBack success, HttpCallBack special, HttpCallBack error, bool hasLoading, BuildContext context}) async { _http(HttpMethod.GET, url, null, success: success, special: special, error: error, hasLoading: hasLoading, context: context); } post(String url, Map map, {HttpCallBack success, HttpCallBack special, HttpCallBack error, bool hasLoading, BuildContext context}) async { _http(HttpMethod.POST, url, map, success: success, special: special, error: error, hasLoading: hasLoading, context: context); } delete(String url, Map map, {HttpCallBack success, HttpCallBack special, HttpCallBack error, bool hasLoading, BuildContext context}) async { _http(HttpMethod.DELETE, url, map, success: success, special: special, error: error, hasLoading: hasLoading, context: context); } put(String url, Map map, {HttpCallBack success, HttpCallBack special, HttpCallBack error, bool hasLoading, BuildContext context}) async { _http(HttpMethod.PUT, url, map, success: success, special: special, error: error, hasLoading: hasLoading, context: context); } patch(String url, Map map, {HttpCallBack success, HttpCallBack special, HttpCallBack error, bool hasLoading, BuildContext context}) async { _http(HttpMethod.PATCH, url, map, success: success, special: special, error: error, hasLoading: hasLoading, context: context); } _http(HttpMethod method, String url, Map map, {HttpCallBack success, HttpCallBack special, HttpCallBack error, bool hasLoading, BuildContext context}) async { this.context = context; var header = await getHeader(); _options = BaseOptions( connectTimeout: HttpConfig.connectTimeout, receiveTimeout: HttpConfig.receiveTimeout, baseUrl: HttpConfig.baseUrl, headers: { SharedPreConfig.TOKEN: header[SharedPreConfig.TOKEN], SharedPreConfig.LOCATION: header[SharedPreConfig.LOCATION], SharedPreConfig.UUID: header[SharedPreConfig.UUID], SharedPreConfig.USER_AGENT: header[SharedPreConfig.USER_AGENT], SharedPreConfig.NET_STATE: header[SharedPreConfig.NET_STATE] }); _dio = Dio(_options); _dio.interceptors .add(InterceptorsWrapper(onRequest: (RequestOptions options) { print( "\n================================= 请求数据 ================================="); print("method = ${options.method.toString()}"); print("url = ${options.uri.toString()}"); print("headers = ${options.headers}"); print("params = ${options.queryParameters}"); }, onResponse: (Response response) { print( "\n================================= 响应数据开始 ================================="); print("code = ${response.statusCode}"); print("data = ${response.data}"); print( "================================= 响应数据结束 =================================\n"); }, onError: (DioError e) { print( "\n=================================错误响应数据 ================================="); print("type = ${e.type}"); print("message = ${e.message}"); print("stackTrace = ${e.stackTrace}"); print("\n"); })); if (hasLoading != null && context != null) { this.hasLoading = hasLoading; } else { this.hasLoading = false; } showLoadingDialog(); try { Response response = await _getResponse(method, url, map); hiddeLoadingDialog(); if (response.statusCode == 200) { if (response.data['Flag'] == 100) { _httpSuccess(response.data, success); } else { _httpSpecial(response.data, special); } } else { _httpError("网络状况不佳", error); } } catch (e) { _httpError(e.toString(), error); } } _getResponse(HttpMethod method, String url, Map map) async { Response response; switch (method) { case HttpMethod.GET: response = await _dio.get(url); return response; case HttpMethod.POST: response = await _dio.post(url, queryParameters: map); return response; case HttpMethod.PATCH: response = await _dio.patch(url, queryParameters: map); return response; case HttpMethod.DELETE: response = await _dio.delete(url, queryParameters: map); return response; case HttpMethod.PUT: response = await _dio.put(url, queryParameters: map); return response; default: response = await _dio.get(url); return response; } } ///statusCode==200&&Flag==100 _httpSuccess(Map response, HttpCallBack success) { if (success != null) { if (T.toString() == "HttpResponseEntity") { success((HttpResponseEntity.fromJson(response).data)); } else if (T.toString() == "HttpResponseListEntity") { success(HttpResponseListEntity.fromJson(response).data); } else { success(response['FlagString']); } } } ///statusCode==200&&Flag!=100 _httpSpecial(Map response, HttpCallBack special) { ///可以针对不同的Flag 进行处理同一处理 if (special != null) { special(response); } else { switch (response['Flag']) { case HttpFlagCode.FLAG_7: break; default: Fluttertoast.showToast( msg: response['FlagString'], fontSize: 14, toastLength: Toast.LENGTH_SHORT, ); } } } ///statusCode!=200 _httpError(String errorMsg, HttpCallBack error) { print('httpError-----$errorMsg'); if (error != null) { error(ErrorResponse('999', '网络状况不佳').toJson()); } } showLoadingDialog() { if (hasLoading) { showDialog( context: context, //BuildContext对象 barrierDismissible: false, builder: (BuildContext context) { return LoadingDialog(); }); } } hiddeLoadingDialog() { if (hasLoading) { Navigator.pop(context); } } } class ErrorResponse { String Flag; String FlagString; ErrorResponse(this.Flag, this.FlagString); Map toJson() { final Map data = new Map(); data['Flag'] = this.Flag; data['FlagString'] = this.FlagString; return data; } }

 

 

你可能感兴趣的:(flutter)