flutter網(wǎng)絡(luò)請(qǐng)求

在flutter中進(jìn)行網(wǎng)絡(luò)請(qǐng)求有多種方式颖御,這里我使用的是dio扎阶。dio這個(gè)庫(kù)被封裝的很好躲胳,使用起來(lái)也很簡(jiǎn)單蒜鸡,但為了更方便我還是自己在做了簡(jiǎn)單的封裝胯努。整體代碼如下

class HttpRequestManager{

  factory HttpRequestManager() =>getInstance();

  static HttpRequestManager get instance =>getInstance();

  static HttpRequestManager _instance;

  Dio dio;

  static CancelToken cancelToken;


  String baseUrl="http://cardapi.mimiplay.cn/cardtest-api/";

  String baseTestUrl="http://cardapi.mimiplay.cn/cardtest-api/";


  HttpRequestManager._init(){
    dio=new Dio();

    BaseOptions options=BaseOptions(
      baseUrl:GlobalData.isProduct? baseUrl:baseTestUrl,
      connectTimeout: 20000,
      receiveTimeout: 20000,
      headers: {
        "content-type": "application/json;charset=UTF-8"
      },
      contentType: Headers.jsonContentType,//請(qǐng)求類型
      responseType: ResponseType.json,//接收類型
    );
    dio.options=options;

    cancelToken=new CancelToken();

    dio.interceptors.add(InterceptorsWrapper(//攔截器
        onRequest: (RequestOptions options){
          LogOut.I("請(qǐng)求地址:   ${options.uri}");
          LogOut.I("請(qǐng)求參數(shù):   ${options.data}");
        },
        onResponse: (Response e){
//          if (e.statusCode==200) {
//            Map map=json.decode(e.data);
//            BaseResult<T> data=BaseResult.fromJson(map);
//          }
          LogOut.I("服務(wù)器返回?cái)?shù)據(jù)----- ${e.toString()}");
        }
    ));
  }

  static HttpRequestManager getInstance(){
    if (_instance==null) {
      _instance=new HttpRequestManager._init();
    }
    return _instance;
  }

}

代碼也很簡(jiǎn)單牢裳,就是在單例類里對(duì)dio進(jìn)行一些設(shè)置,比如請(qǐng)求超時(shí)叶沛,請(qǐng)求頭蒲讯,返回類型等。然后也可以為其設(shè)置攔截灰署,攔截有三個(gè)方法分別是
onrequest:可以在此方法內(nèi)設(shè)置請(qǐng)求前的操作判帮,比如設(shè)置token等,我這里只是打印了請(qǐng)求地址和參數(shù)
onResponse:此處攔截工作在數(shù)據(jù)返回之后溉箕,可以在方法內(nèi)對(duì)dio請(qǐng)求的數(shù)據(jù)做二次封裝或者轉(zhuǎn)實(shí)體類等相關(guān)操作
onError:處理錯(cuò)誤

做完了對(duì)dio的基本封裝晦墙,下面就看下怎么使用其做網(wǎng)絡(luò)請(qǐng)求,并對(duì)數(shù)據(jù)進(jìn)行網(wǎng)絡(luò)解析约巷。具體代碼如下

typedef CallBackSuccess =Function(BaseResult result);//設(shè)置請(qǐng)求成功方法
typedef CallBackFail =Function(String message);//設(shè)置請(qǐng)求失敗方法



class HttpRequest{

  static void postRequest(String url,{Map<String, dynamic> data,CancelToken cancelToken,Options options,CallBackSuccess success,CallBackFail fail}) async{
    try {
      options=options??Options(method: "POST");//默認(rèn)請(qǐng)求方法為post
      Response response= await HttpRequestManager.instance.dio.request
        (url,data:data,cancelToken:cancelToken,options: options);

      if (response.statusCode==200) {


        Map<String, dynamic> map=json.decode(response.toString());//請(qǐng)求成功將數(shù)據(jù)轉(zhuǎn)化成map
        LogOut.I("data類型 ${map["data"].runtimeType}");//得到map里data的數(shù)據(jù)類型偎痛,方便接下來(lái)根據(jù)數(shù)據(jù)類型做解析
        BaseResult result;//數(shù)據(jù)基類

        if (map["data"] == null) {//data為null
          result=BaseResult.fromNoData(map);
        }else if (map["data"] is Map) {//data為map類型
          result=BaseResult.fromJson(map);
        }else if(map["data"] is List){//data為list類型
          LogOut.I("list類型");
          result=BaseResult.fromJsonList(map);
        }else if(map["data"] is String){//data為字符串
          result=BaseResult.fromString(map);
        }

        if(result.code=="900002"){
          //todo 登錄失效處理
          Fluttertoast.showToast(msg: result.message);
          SPUtil util=await SPUtil.getInstances();
          await util.setString("userId", "");
          await util.setString("tokenId", "");
          await util.setString("phone", "");
          LogOut.I("登錄失效");
          fail(result.message);
          MyRouters.navigatorKey.currentState.push(MaterialPageRoute(builder: (context){
            return new LoginPage();//登陸失效返回登錄頁(yè)
          },));
        }else{
          if (success!=null) {
            success(result);
          }
        }
      }else{
        if (fail!=null) {
          fail(response.statusMessage+"錯(cuò)誤地址:$url");
        }else{
          Fluttertoast.showToast(msg: response.statusMessage);

        }
      }
    } catch (e) {
      print(e);
      if (fail!=null) {
        fail(e.toString()+"錯(cuò)誤地址:$url");
      }
//      callBack.fail(e.toString()+"錯(cuò)誤地址:$url");

    }
  }
}

在上面的代碼中,網(wǎng)絡(luò)請(qǐng)求方法默認(rèn)為post独郎,同時(shí)也做了數(shù)據(jù)解析踩麦。在flutter中數(shù)據(jù)解析不想Android那樣方便,我這里是對(duì)其進(jìn)行了分類型解析氓癌,這樣不管后臺(tái)返回的data為何種類型都有對(duì)應(yīng)的解析方式谓谦。解析成功后就是看自己的需求做操作了,我在這里做了登錄失效和請(qǐng)求成功的處理贪婉。成功時(shí)反粥,將baseresult傳入success方法里。至于baseresult是怎么分類型進(jìn)行解析的疲迂,我這里借助了FlutterJsonBeanFactory這個(gè)插件實(shí)現(xiàn)的才顿。下面看baseresult的具體代碼

class BaseResult<T>{
  String code;
  String message;

  List<dynamic> listResult;

  Map<String, dynamic> result;

  String data;

  BaseResult({this.code, this.message, this.listResult,this.result,this.data});

  factory BaseResult.fromJsonList(Map<String, dynamic> json) {//data為list
    return BaseResult(
      code:json['code'],
      message: json['message'],
      listResult: json['data'],
    );

  }

  factory BaseResult.fromNoData(Map<String, dynamic> json) {//data為空
    return BaseResult(
      code:json['code'],
      message: json['message'],
    );
  }

  factory BaseResult.fromJson(Map<String, dynamic> json) {//data為map
    return BaseResult(
      code:json['code'],
      message: json['message'],
      result: json['data'],
    );

  }

  factory BaseResult.fromString(Map<String, dynamic> json) {//data為lString
    return BaseResult(
      code:json['code'],
      message: json['message'],
      data: json['data'],
    );

  }

  List<T> getListData<T>(){//data為list,得到data
    List<T> list=new List<T>();
    if (listResult!=null) {
      listResult.forEach((value) {
        list.add(JsonConvert.fromJsonAsT<T>(value));//插件方法
      });

    }
    return list;
  }


  T getMapData<T>(){//data為map尤蒿,得到data
    LogOut.I("result $result");
    return JsonConvert.fromJsonAsT<T>(result);//插件方法
  }

  String getData(){//data為string郑气,得到data
    return data;
  }


  @override
  String toString() {
    return 'BaseResult{code: $code, message: $message, listResult: $listResult, result: $result, data: $data}';
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['code'] = this.code;
    data['message'] = this.message;
    if (this.result != null) {
      data['data'] = this.result;
    }else if(this.listResult != null){
      data['data'] = this.listResult;
    }else if(this.data!=null){
      data['data'] = this.data;
    }
    return data;
  }
}

上面網(wǎng)絡(luò)封裝和數(shù)據(jù)解析都已經(jīng)準(zhǔn)備好了,接下來(lái)就是調(diào)用的問(wèn)題了腰池,我這里做了一個(gè)類專門(mén)放各個(gè)接口請(qǐng)求尾组。具體代碼如下

class RequestUtil{

  factory RequestUtil() =>getInstances();

  static RequestUtil get requestUtil =>getInstances();
  RequestUtil._init();

  static RequestUtil _requestUtil;

  static RequestUtil getInstances(){
    if (_requestUtil==null) {
      _requestUtil=new RequestUtil._init();

    }
    return _requestUtil;
  }

  Future<Map<String, dynamic>> _setBaseMap() async{//固定參數(shù)
    LoginManager loginManager=LoginManager.getInstances();
    LoginInfo info=await loginManager.getLogin();
    String userId=info.userId;
    String tokenId=info.tokenId;
    Map<String, dynamic> map={
      "userId":userId,
      "tokenId":tokenId,
      "clientVersion":clientVersion,
      "clientType":clientType
    };

    return map;
  }
///消息公告
  getMessage(Map<String, dynamic> data,{success(BaseResult result),fail(message)}) async{
    String url="notice/find/message";
    Map<String, dynamic> map=await _setBaseMap();
    map.addAll(data);
    HttpRequest.postRequest(url,data: map,success:success,fail: fail);
  }

///得到用戶信息
  getUserInfo({success(BaseResult result),fail(message)}) async{
    String url="account/userAccount/108/myAccountInfo";
    Map<String, dynamic> map=await _setBaseMap();
    HttpRequest.postRequest(url,data: map,success:success,fail: fail);
  }
  ///登錄
  doLogin(Map<String, dynamic> data,{success(BaseResult result),fail(message)}) async{
    String url="auth/login/normal";
    Map<String, dynamic> map=await _setBaseMap();
    map.addAll(data);
    HttpRequest.postRequest(url,data: map,success:success,fail: fail);
  }
}

然后就是調(diào)用了,這里展示data為map類型和list類型的調(diào)用示弓。首先是map類型

 RequestUtil.getInstances().doLogin({
      "userMobileNo":userPhone,
      "userPass":pass,
    }, success: (result){//成功回調(diào)
      LoginResult resultLogin=result.getMapData<LoginResult>();//通過(guò)baseresult的getMapData得到data
      LogOut.I("${resultLogin.toString()}");
    },fail: (message){

    });

然后是list類型

void getMessage(){
    RequestUtil.getInstances().getMessage({
      "pageNum":1,
      "pageSize":15
    }, success: (result){
      controller.refreshCompleted();
      List<MessageResult> list=result.getListData<MessageResult>();//通過(guò)baseresult的getListData得到data
   
      LogOut.I("解析后 $list");
    },fail: (message){
    });
  }

到這里就將我自己做的flutter關(guān)于dio的網(wǎng)絡(luò)請(qǐng)求與數(shù)據(jù)解析說(shuō)完了讳侨,我個(gè)人覺(jué)得比較煩人的還是在數(shù)據(jù)解析這方面,關(guān)于flutter的數(shù)據(jù)解析還有多種方法奏属,比如使用json_serializable跨跨,我這里覺(jué)得這種方式比較舒服就是用了這種。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拍皮,一起剝皮案震驚了整個(gè)濱河市歹叮,隨后出現(xiàn)的幾起案子跑杭,更是在濱河造成了極大的恐慌,老刑警劉巖咆耿,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件德谅,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡萨螺,警方通過(guò)查閱死者的電腦和手機(jī)窄做,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)慰技,“玉大人椭盏,你說(shuō)我怎么就攤上這事∥巧蹋” “怎么了掏颊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)艾帐。 經(jīng)常有香客問(wèn)我乌叶,道長(zhǎng),這世上最難降的妖魔是什么柒爸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任准浴,我火速辦了婚禮,結(jié)果婚禮上捎稚,老公的妹妹穿的比我還像新娘乐横。我一直安慰自己,他們只是感情好今野,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布葡公。 她就那樣靜靜地躺著,像睡著了一般条霜。 火紅的嫁衣襯著肌膚如雪匾南。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天蛔外,我揣著相機(jī)與錄音,去河邊找鬼溯乒。 笑死夹厌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裆悄。 我是一名探鬼主播矛纹,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼光稼!你這毒婦竟也來(lái)了或南?” 一聲冷哼從身側(cè)響起孩等,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎采够,沒(méi)想到半個(gè)月后肄方,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹬癌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年权她,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逝薪。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隅要,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出董济,到底是詐尸還是另有隱情步清,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布虏肾,位于F島的核電站廓啊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏询微。R本人自食惡果不足惜崖瞭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撑毛。 院中可真熱鬧书聚,春花似錦、人聲如沸藻雌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胯杭。三九已至驯杜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間做个,已是汗流浹背鸽心。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留居暖,地道東北人顽频。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像太闺,于是被迫代替她去往敵國(guó)和親糯景。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容