dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等...

最近想用flutter写个商城项目,下载一些demo后发现dio都不封装下就使用,像使用flutter的大多数都是Android开发转过来的,习惯性封装okhttp,将 Response 里返回的数据在工具类里处理好再返回业务层处理,从而大大减少代码量,使之更加清晰简洁,接下来代码走起...

 

 

目录

一、示例使用

二、依赖库

三、创建一个Dio实例以及Dio封装

四、Dio拦截器

五、JSON解析


 

一、示例使用

 

一个登陆操作的post请求

var APILongin="http://192.168.1.144:8085/sso/login";

_LoginPost() {
    ///入参
    Map<String, dynamic> map = Map();  
      map.putIfAbsent("username", () => "10086");
      map.putIfAbsent("password", () => "132456";
      DioUtils.instance.postHttp<TokenBeanEntity>(url: APILongin,parameters: map,onSuccess:            
     (datas){ 
        print(datas);
         
      }, onError: (error){
                print("error");
      });
    }
}

_LoginPost() {
    ///入参
    Map<String, dynamic> map = Map();  
      map.putIfAbsent("username", () => "10086");
      map.putIfAbsent("password", () => "132456";
      DioUtils.instance.postHttp<TokenBeanEntity>(url: APILongin,parameters: map,onSuccess:            
     (datas){ 
        print(datas);
         
      }, onError: (error){
                print("error");
      });
    }
}

// patch put  delect get post 都可以使用,添加 method 即可
_LoginPut() {
    ///入参
    Map<String, dynamic> map = Map();  
      map.putIfAbsent("username", () => "10086");
      map.putIfAbsent("password", () => "132456";
      DioUtils.instance.getHttp<TokenBeanEntity>(url: APILongin,method : DioUtils.GET ,parameters: map,onSuccess:            
     (datas){ 
        print(datas);
         
      }, onError: (error){
                print("error");
      });
    }
}

不需要返回参数

 

第一种方式
/// 无参数返回 get
 get DioUtils.instance.getHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" );


/// 无参数返回 post 
 get DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" );


第二种方式
/// 无参数返回 get
 DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" ,
method : DioUtils.GET  );


/// 无参数返回 post
  DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" ,
method : DioUtils.POST);

/// 无参数返回 delete
  DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" ,
method : DioUtils.DELETE);

 

 

 

二、依赖库

打开pubspec.yaml ,添加dio依赖即可,然后pubget

dependencies:
  flutter:
    sdk: flutter
    dio: ^3.0.9 /// 添加flutter中文网最新的即可

 

三、创建一个Dio实例以及Dio封装

  创建DioUtils.dart工具类

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:mall/api/api.dart';
import 'package:mall/http/BaseBean.dart';
import 'package:mall/http/LogInterceptors.dart';

class DioUtils {
  static var dio;
  static var httpUtil;

  static DioUtils get instance => _getInstance();
  static DioUtils _getInstance() {
    if (httpUtil == null) {
      httpUtil = DioUtils();
    }
    return httpUtil;
  }

  static const String API_PREFIX = 'https://novel.dkvirus.com/api/v1';
  static const int CONNECT_TIMEOUT = 10000;
  static const int RECEIVE_TIMEOUT = 10000;

  static const String GET = 'get';
  static const String POST = 'post';
  static const String PUT = 'put';
  static const String PATCH = 'patch';
  static const String DELETE = 'delete';

  ///Get请求
  void getHttp <T>( {  String url, parameters, Function(T t) onSuccess,  Function(String error) onError, }) async {
    try {
      Dio dio = createInstance();
      Response response = await dio.get(Api.BASE_URL);
      response=  await dio.get((url==null||url.isEmpty)?Api.BASE_URL : url,queryParameters: parameters);
      getResponse(url: url,method :GET ,parameters: parameters,onSuccess: onSuccess,onError: onError);
    } catch (e) {
      print(e);
    }
  }

  ///Post请求 && put delect...
  void postHttp<T>(
      {  String url,
        String method,
        parameters,
        Function(T t) onSuccess,
        Function(String error) onError,
      })  async {

    ///定义请求参数
    parameters = parameters ?? {};
    getResponse(url: url,parameters: parameters,onSuccess: onSuccess,onError: onError);
  }
  void getResponse<T>({  String url, String method, parameters, Function(T t) onSuccess,  Function(String error) onError, }) async {
    try {
      Response response;
      Dio dio = createInstance();
      switch(method){
        case GET:
          response=  await dio.get((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
          break;
        case PUT:
          response=  await dio.put((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
          break;
        case PATCH:
          response=  await dio.patch((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
          break;
        case DELETE:
          response=  await dio.delete((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
          break;
        default:
          response=  await dio.post((url==null||url.isEmpty)?Api.BASE_URL : url, data: parameters);
          break;
      }
/// 拦截http层异常码
      if (response.statusCode == 200) {
/// 这里做baseBena泛型解析,封装 并拦截后台code异常码,可拦截自定义处理 
        BaseBean<T>bean=BaseBean.fromJson(response.data);
        if(bean.code==200&&onSuccess != null){
/// 返回泛型Bean
          onSuccess( bean.data);
        }else{
          onError(bean.message);
        }
      } else {
        throw Exception('statusCode:${response.statusCode}+${response.statusMessage}');
      }
    } catch (e) {
      print('请求出错:' + e.toString());
      onError(e.toString());
    }
  }
  /// @ url 请求链接
  ///@ parameters 请求参数
  ///@ metthod 请求方式
  ///@ onSuccess 成功回调
  ///@ onError 失败回调
  Future<Map> request<T>(String url,
      {parameters,
        method,
        Function(T t) onSuccess,
        Function(String error) onError}) async {
    parameters = parameters ?? {};
    method = method ?? 'GET';

    /// 请求处理
    parameters.forEach((key, value) {
      if (url.indexOf(key) != -1) {
        url = url.replaceAll(':$key', value.toString());
      }
    });

    Dio dio = createInstance();
    //请求结果
    var result;
    try {
      Response response = await dio.request(url,
          data: parameters, options: new Options(method: method));
      result = response.data;
      if (response.statusCode == 200) {
        if (onSuccess != null) {
          var data = json.decode(response.data) ;
          onSuccess(data);
        }
      } else {
        throw Exception('statusCode:${response.statusCode}');
      }
    } on DioError catch (e) {
      print('请求出错:' + e.toString());
      onError(e.toString());
    }

    return result;
  }
/// 初始化DIO
  Dio createInstance() {
    if (dio == null) {
      /// 全局属性:请求前缀、连接超时时间、响应超时时间
      var options = BaseOptions(
        connectTimeout: 15000,
        receiveTimeout: 15000,
        //responseType: ResponseType.plain,
        validateStatus: (status) {
          // 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)
          return true;
        },
        //  baseUrl: "http://poetry.huhustory.com/",
      );
      dio = new Dio(options);
/// 增加拦截器并添加heands头 token
      dio.interceptors.add(LogInterceptors(dio));
    }

    return dio;
  }
  /// 清空 dio 对象
  clear() {
    dio = null;
  }
}

  

四、Dio拦截器

import 'package:dio/dio.dart';
import 'package:mall/utils/shared_preferences_util.dart';

///日志拦截器
class LogInterceptors extends InterceptorsWrapper {
  Dio dio;

  LogInterceptors(this.dio);

  @override
  Future onRequest(RequestOptions options) async {
    print("========================请求数据===================");
    print("【请求baseUrl】${options.uri}");
//    print("【请求path】${options.path}");
//    print("【请求headers】${options.headers.toString()}");
    print("【请求参数】${options.data.toString()}");
    dio.lock();
     await SharedPreferencesUtils.getToken().then((token) {
      if(token==null||token.toString().isEmpty){
        return;
      }
      Map<String,String> parms = {"Authorization" : "Bearer "+token};
      options.headers.addAll(parms);
    });
    dio.unlock();
    return options;
    return super.onRequest(options);
  }

  @override
  Future onResponse(Response response) {
    print("【返回statusCode】${response.statusCode}");
//    print("【返回headers】${response.headers.toString()}");
//    print("【返回extra】${response.extra.toString()}");
    print("【返回data】${response.data.toString()}");
    return super.onResponse(response);
  }

  @override
  Future onError(DioError err) {
    print("========================请求错误===================");
    formatError(err);
    return super.onError(err);
  }

  ///  error统一处理
  void formatError(DioError e) {
    if (e.type == DioErrorType.CONNECT_TIMEOUT) {
      print(e.hashCode.toString() + "连接超时");
    } else if (e.type == DioErrorType.SEND_TIMEOUT) {
      print(e.hashCode.toString() + "请求超时");
    } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
      print(e.hashCode.toString() + "响应超时");
    } else if (e.type == DioErrorType.RESPONSE) {
      print(e.hashCode.toString() + "出现异常404 503");
    } else if (e.type == DioErrorType.CANCEL) {
      print(e.hashCode.toString() + "请求取消");
    } else {
      print("message =${e.message}");
    }
  }
}

五、JSON解析

 

这里BaseBean<UserBeanEntity>泛型解析 使用插件FlutterJsonBeanFactory生成dart class实体类,androidStudio用户可以下载FlutterJsonBeanFactory插件,然后重启AS

泛型解析这边是刚好看到一锅子鱼这位兄弟的的博客改写的,大家可以去看下

创建 BaseBean<T> ,安装好FlutterJsonBeanFactory的时候new JsonToDartBeanAction,会自动生成json_convert_content.dart文件在项目中,并且会在JsonConvert里生成fromJsonAsT方法

import 'package:mall/generated/json/base/json_convert_content.dart';

///convert和FlutterJsonBeanFactory结合解析
class BaseBean<T> {
	T data;
	int code;
	String message;

	BaseBean({this.data, this.code, this.message});

	BaseBean.fromJson(Map<String, dynamic> json) {
		if (json['data'] != null&&json['data']!='null') {
			data = JsonConvert.fromJsonAsT<T>(json['data']);
		}
		code = json['code'];
		message = json['message'];
	}

	Map<String, dynamic> toJson() {
		final Map<String, dynamic> data = new Map<String, dynamic>();
		if (this.data != null) {
			data['data'] = this.data;
		}
		data['code'] = this.code;
		data['message'] = this.message;
		return data;
	}
}
import 'package:mall/generated/json/base/json_convert_content.dart';

class TokenBeanEntity with JsonConvert<TokenBeanEntity> {
	String tokenHead;
	String token;
}

 

完结...


Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐