Flutter Dio網絡請求封裝(GET,POST,圖片上傳)

一、前言

最近學習Flutter進行到了網絡這一塊,所以就花了點時間對網絡請求進行了簡單的封裝,以便使用,網絡請求基于Dio,具體使用可自行學習。

二、結構

  • net.dart 基于Dio封裝的get, post請求
  • net_url.dart 對請求地址的統一管理
  • net_util.dart 對net的二次封裝,將地址添加進來,統一管理網絡請求
image.png

三、代碼

  • net.dart,代碼里都有注釋
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:demo/model/base_model.dart';
/// 自定義枚舉
enum Method {
  get,
  post
}

class Net{
  // 工廠模式
  factory Net() => _getInstance();
  static Net get instance => _getInstance();
  static Net _instance;

  Dio dio;
  Net._internal() {
    // 初始化
    dio = Dio(BaseOptions(
      connectTimeout: 60000,   // 連接服務器超時時間,單位是毫秒.
      receiveTimeout: 10000,   // 響應流上前后兩次接受到數據的間隔,單位為毫秒, 這并不是接收數據的總時限.
      )
    );
  }
  // 單列模式
  static Net _getInstance() {
    if (_instance == null){
      _instance = Net._internal();
    }
    return _instance;
  }

  get(String url, Map<String,dynamic> params, {Function success,Function failure}){
    _doRequest(url, params, Method.get, success, failure);
  }

  post(String url, Map<String,dynamic> params, {Function success,Function failure}){
    _doRequest(url, params, Method.post, success, failure);
  }

  void _doRequest(String url, Map<String,dynamic> params ,Method method, Function successCallBack, Function failureCallBack) async{
      try{
     /// 可以添加header
     //  dio.options.headers.addAll({'token':xxx});
        Response response;
        switch (method){
          case Method.get:
            if (params != null && params.isNotEmpty){
              response = await dio.get(url,queryParameters: params);
            }else {
              response = await dio.get(url);
            }
            break;
          case Method.post:
            if (params != null && params.isNotEmpty){
              response = await dio.post(url,queryParameters: params);
            }else {
              response = await dio.post(url);
            }
            break;
        }
        Map<String, dynamic> result = json.decode(response.toString());
        // 打印信息
        print('''api: $url\nparams: $params\nresult: $result''');
       // 轉化為model
        BaseModel model = BaseModel.fromJson(result);
        if (model.code == 200){ // 200 請求成功
          if (successCallBack != null){//返回請求數據
            successCallBack(model.data);
          }
        }else {
          //TODO
          //直接使用Toast彈出錯誤信息
          //返回失敗信息
           if (failureCallBack != null){
             failureCallBack(model.error);
           }
        }
      }catch (exception){
        print('錯誤:${exception.toString()}');
        Fluttertoast.showToast(msg: "請求失敗,請稍后再試");
        if (failureCallBack != null){
          failureCallBack(exception.toString());
        }
      }
  }

// 上傳文件(圖片)
doUploadFile(String url, File file, String loadingText,Function successCallBack,
      Function failureCallBack) async {
    try {
      String timeStamp = DateTime.now().millisecondsSinceEpoch.toString();
      FormData formData = FormData.from({
        'file': UploadFileInfo(file, '$timeStamp.jpg',
            contentType: ContentType.parse("image/jpeg"))
      });
      Response response = await dio.post(url, data: formData);
      print('$response'); // 在需要生成model時需要json格式
      Map<String, dynamic> result = json.decode(response.toString());
      assert(() {
        // assert只會在debug模式下執行,release模式下不會執行
        // 打印信息
        print('''api: $url\nresult: $result''');
        return true;
      }());

      BaseModel model = BaseModel.fromJson(result);
      if (model.code == 200) {
        // 200 請求成功
        if (successCallBack != null) {
          if (model.data != null) {
            successCallBack(model.data);
          } else {
            successCallBack({});
          }
        }
      } else {
        //Fluttertoast.showToast(msg: "${model.msg}");
        if (failureCallBack != null) {
          failureCallBack(model.msg);
        }
      }
    } catch (exception) { 
      assert(() {
        // 打印信息
        print('''api: $url\n錯誤:${exception.toString()}''');
        return true;
      }());

    //  Fluttertoast.showToast(msg: '加載失敗');
      if (failureCallBack != null) {
        failureCallBack(exception.toString());
      }
    }
  }

}
  • base_model.dart 上面使用到的model類
class BaseModel {
  int code;
  dynamic data;
  String error;

  BaseModel({this.code, this.data, this.error});

  BaseModel.fromJson(Map<String, dynamic> json) {
    code = json['code'];
    data = json['data'];
    error = json['error'];
  }
}
  • net_url.dart 請求地址
class NetUrl {
  /// 服務器地址
  static const String BASE_URL = "http://www.dio.com";
  /// 登錄接口
  static const String LOGIN_USER  = BASE_URL + '/login';
}
  • net_util.dart 請求的二次封裝,具體到某個請求,隱藏接口
import "net.dart";
import 'net_url.dart';
class NetUtil {
  // 登錄
   static void login(Map<String,dynamic> params,{Function success, Function failure}){
      Net().post(NetUrl.LOGIN_USER, params,success: success, failure: failure);
   }
}

4、具體使用

 void requestData(){
    var params = {'username':'xxx','password':'xxxx'};
    NetUtil.login(params,success: (response){

    },failure: (error){
      
    });
  }

5、總結

以上封裝還有幾點待完善

  • 1、可以加上請求時的HUD,請求成功就消失掉
  • 2、在net.dart,TODO的地方使用toast彈出錯誤信息,相當于將錯誤信息集中處理
    至此網絡請求封裝與使用都完成了,有什么問題歡迎留言探討,如果對你有幫助或者你喜歡的話,給個贊吧??!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容