Flutter實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求的方法示例
Flutter網(wǎng)絡(luò)請(qǐng)求使用的是Dio。Dio是一個(gè)強(qiáng)大易用的dart http請(qǐng)求庫,支持Restful API、FormData、攔截器、請(qǐng)求取消、Cookie管理、文件上傳/下載.......
Flutter json數(shù)據(jù)解析是使用了json_serializable package包。它是一個(gè)自動(dòng)化源代碼生成器,可以為我們生成JSON序列化模板。由于序列化代碼不再由我們手寫和維護(hù),我們將運(yùn)行時(shí)產(chǎn)生JSON序列化異常的風(fēng)險(xiǎn)降至最低。
Flutter網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)并且展示效果圖:
數(shù)據(jù)接口
數(shù)據(jù)是使用的聚合數(shù)據(jù)的API,影訊API合集,大家可以注冊(cè)個(gè)賬號(hào),申請(qǐng)使用一下,像這樣
添加依賴
在pubspec.yaml文件中添加所需要的第三方依賴庫
environment: sdk: ">=2.1.0 <3.0.0" dependencies: flutter: sdk: flutter json_annotation: ^2.0.0 connectivity: ^0.4.2 dio: ^2.0.15 event_bus: ^1.0.3 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 dev_dependencies: flutter_test: sdk: flutter
網(wǎng)絡(luò)請(qǐng)求過程分析
static netFetch(url,params,Map<String,String> header,Options option,{noTip = false}) async { //獲取網(wǎng)絡(luò)的連接狀態(tài),如果沒有連接網(wǎng)絡(luò),返回NETWORK_ERROR var connectivityResult = await (new Connectivity().checkConnectivity()); if(connectivityResult == ConnectivityResult.none) { return new ResultData(Code.errorHandleFunction(Code.NETWORK_ERROR, "", noTip),false,Code.NETWORK_ERROR); } //請(qǐng)求頭存放集合 Map<String,String> headers = new HashMap(); if(header != null) { headers.addAll(header); } //option存放請(qǐng)求的一些配置信息 if(option != null) { option.headers = headers; }else { //get請(qǐng)求 option = new Options(method:'get'); option.headers = headers; } //超時(shí)時(shí)間15000ms option.connectTimeout = 15000; //創(chuàng)建dio對(duì)象 Dio dio = new Dio(); Response response; try{ //執(zhí)行網(wǎng)絡(luò)請(qǐng)求,await和async配合使用,表示這是一個(gè)異步耗時(shí)操作 //執(zhí)行結(jié)果不會(huì)立馬返回。 response = await dio.request(url,data: params,options: option); }on DioError catch(e) { //異常處理 .... return new ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip), false, errorResponse.statusCode); } try{ if(response.statusCode == 200 || response.statusCode == 201) { //網(wǎng)絡(luò)請(qǐng)求成功 return await new ResultData(response.data, true, Code.SUCCESS,headers: response.headers); } }catch(e) { //異常處理 print('返回參數(shù)' + e.toString() + url); return new ResultData(response.data, false, response.statusCode,headers: response.headers); } return new ResultData(Code.errorHandleFunction(response.statusCode, "", noTip), false, response.statusCode); }
這個(gè)是最底層類封裝了一個(gè)靜態(tài)的請(qǐng)求方法,直接調(diào)用dio的request方法進(jìn)行網(wǎng)路請(qǐng)求,很簡單。
//如果這個(gè)是耗時(shí)方法,就會(huì)用async標(biāo)記,耗時(shí)操作用await標(biāo)記,表示是一個(gè)異步操作。 static getTodayFilmListDao() async { //獲取請(qǐng)求的url String url = Address.getTodayFilmList(); //調(diào)用上面封裝的網(wǎng)絡(luò)請(qǐng)求方法進(jìn)行網(wǎng)絡(luò)請(qǐng)求 var res = await HttpManager.netFetch(url, null, null, null); if(res != null && res.result) { var data = res.data; if(data == null || data.length == 0) { return await new DataResult([],true); } //網(wǎng)絡(luò)請(qǐng)求成功,進(jìn)行數(shù)據(jù)解析 var response = TodayFilmResponse.fromJson(data); //返回?cái)?shù)據(jù) return await new DataResult(response.result,true); }else { return await new DataResult(null,false); } }
獲取url方法很簡單,就是字符串拼接了一下
static getTodayFilmList() { return "${host}movie/movies.today?cityid=1&dtype=&key=713a408e855352d913806ef1e3ce3c33"; }
下面分析一下json數(shù)據(jù)解析過程。
如上所說,json解析使用的是json_serializable package包。它是一個(gè)自動(dòng)化源代碼生成器,可以為我們生成JSON序列化模板。
網(wǎng)絡(luò)請(qǐng)求獲取到的json數(shù)據(jù)是這樣的
{ "movieId":"135808", "movieName":"新喜劇之王", "pic_url":"http:\/\/img5.mtime.cn\/mt\/2019\/02\/02\/113216.53857992_182X243X4.jpg" }, TodayFilmBean類 //TodayFilmBean.g.dart將在我們運(yùn)行生成命令之后自動(dòng)生成 part 'TodayFilmBean.g.dart'; //這個(gè)標(biāo)注是告訴生成器,這個(gè)類是要生成的Model類 @JsonSerializable() class TodayFilmBean{ String movieId; String movieName; String pic_url; //構(gòu)造函數(shù) TodayFilmBean(this.movieId,this.movieName,this.pic_url); //json轉(zhuǎn)換為bean對(duì)象 factory TodayFilmBean.fromJson(Map<String,dynamic> json) => _$todayFilmBeanFromJson(json); //bean對(duì)象轉(zhuǎn)換為json Map<String,dynamic> toJson() => _$todayFilmBeanToJson(this); } 生成的TodayFilmBean.g.dart類是這樣的 part of 'TodayFilmBean.dart'; //json轉(zhuǎn)換為bean對(duì)象 TodayFilmBean _$todayFilmBeanFromJson(Map<String,dynamic> json) { return TodayFilmBean(json['movieId'] as String,json['movieName'] as String, json['pic_url'] as String); } //bean對(duì)象轉(zhuǎn)換為json Map<String,dynamic> _$todayFilmBeanToJson(TodayFilmBean instance) => <String,dynamic> { 'movieId': instance.movieId, 'movieName': instance.movieName, 'pic_url':instance.pic_url };
有兩種運(yùn)行代碼生成器的方法:
1.一次性生成
通過在我們的項(xiàng)目根目錄下運(yùn)行flutter packages pub run build_runner build,我們可以在需要時(shí)為我們的model生成json序列化代碼。這觸發(fā)了一次性構(gòu)建,它通過我們的源文件,挑選相關(guān)的并為它們生成必要的序列化代碼。
雖然這非常方便,但如果我們不需要每次在model類中進(jìn)行更改時(shí)都要手動(dòng)運(yùn)行構(gòu)建命令的話會(huì)更好。
2.持續(xù)生成
使用_watcher_可以使我們的源代碼生成的過程更加方便。它會(huì)監(jiān)視我們項(xiàng)目中文件的變化,并且在需要時(shí)自動(dòng)構(gòu)建必要的文件。我們可以通過flutter packages pub run build_runner watch 在項(xiàng)目根目錄下運(yùn)行來啟動(dòng)_watcher_。
只需啟動(dòng)一次觀察器,然后并讓它在后臺(tái)運(yùn)行,這是安全的。
執(zhí)行序列化只需執(zhí)行
//把json數(shù)據(jù)轉(zhuǎn)化為了bean對(duì)象 var filmBean = TodayFilmBean.fromJson(json);
使用GridView最終展示結(jié)果
DataResult dataResult; List<TodayFilmBean> mData = []; //當(dāng)StatefulWiget被嵌入此view樹中,就會(huì)為此widget創(chuàng)建State對(duì)象 //當(dāng)State對(duì)象被創(chuàng)建了,frameWork就會(huì)調(diào)用initState()方法 @override void initState() { //初始化數(shù)據(jù) getTodayFilm(); super.initState(); } void getTodayFilm() async { //這是一個(gè)異步操作,結(jié)果返回有一定延遲 dataResult = await TodayDao.getTodayFilmListDao(); //調(diào)用setState方法會(huì)通知framework控件狀態(tài)有變化,它會(huì)立馬觸發(fā) //State的build方法更新widget狀態(tài) setState(() { mData = dataResult.data; }); }
上面是初始化網(wǎng)絡(luò)請(qǐng)求,在請(qǐng)求到數(shù)據(jù)后,調(diào)用setState刷新UI
//State的build方法,調(diào)用setState方法后,此方法就會(huì)被觸發(fā) //用來刷新UI @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), //如果mData.length == 0,展示一個(gè)loading框,否則展示數(shù)據(jù) body: mData.length == 0 ? new Center(child: new CircularProgressIndicator()): //創(chuàng)建GridView對(duì)象 new GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, //每行2個(gè) mainAxisSpacing: 1.0, //主軸(豎直)方向間距 crossAxisSpacing: 1.0, //縱軸(水平)方向間距 childAspectRatio: 0.7 //縱軸縮放比例 ), //item數(shù)量 itemCount:mData.length, //創(chuàng)建每個(gè)item itemBuilder: (BuildContext context,int index) { return _getWidget(index); }), ); } _getWidget(int index) { //添加要展示的item內(nèi)容 return new Column( children: <Widget>[ new Expanded(child: new CardItem(color: Colors.black12,child: _getChild(index)),flex: 8,), //顯示網(wǎng)絡(luò)請(qǐng)求文本 new Expanded(child: new Text(mData[index].movieName, textAlign: TextAlign.end, maxLines: 1, ), flex:1) ]); } _getChild(int i) { return new Padding(padding: new EdgeInsets.all(1.0), //顯示網(wǎng)絡(luò)請(qǐng)求的圖片 child: new Image(image: NetworkImage(mData[i].pic_url))); }
一個(gè)自定義的CardItem
class CardItem extends StatelessWidget{ final Widget child; final EdgeInsets margin; final Color color; final RoundedRectangleBorder shape; final double elevation; CardItem({@required this.color,this.child,this.elevation = 5.0,this.shape,this.margin}); @override Widget build(BuildContext context) { EdgeInsets margin = this.margin; RoundedRectangleBorder shape = this.shape; Color color = this.color; margin ??= EdgeInsets.only(left: 2.0,top: 2.0,right: 2.0,bottom: 2.0); shape ??= new RoundedRectangleBorder(borderRadius: new BorderRadius.all(Radius.circular(4.0))); color ??= new Color(0xffeeff); return new Card(elevation: elevation,shape: shape,color: color,margin: margin,child: child,); } }
好了,F(xiàn)lutter網(wǎng)絡(luò)請(qǐng)求并且展示數(shù)據(jù)就這樣實(shí)現(xiàn)的。
最后附上demo地址: https://github.com/xinhuashi/flutter_http_demo.git
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android用于校驗(yàn)集合參數(shù)的小封裝示例
本篇文章主要介紹了Android-用于校驗(yàn)集合參數(shù)的小封裝示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10詳解Flutter WebView與JS互相調(diào)用簡易指南
這篇文章主要介紹了詳解Flutter WebView與JS互相調(diào)用簡易指南,分為JS調(diào)用Flutter和Flutter調(diào)用JS,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-04-04Android中實(shí)現(xiàn)EditText密碼顯示隱藏的方法
這篇文章主要介紹了Android中實(shí)現(xiàn)EditText密碼顯示隱藏的方法,需要的朋友可以參考下2017-01-01Android 簡單實(shí)現(xiàn)一個(gè)流式布局的示例
本篇文章主要介紹了Android 簡單實(shí)現(xiàn)一個(gè)流式布局的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02丟失Android系統(tǒng)庫或者Conversion to Dalvik format failed with error
這篇文章主要介紹了丟失Android系統(tǒng)庫或者Conversion to Dalvik format failed with error 1錯(cuò)誤的解決方法,分析了Android系統(tǒng)庫丟失及版本問題的處理技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-12-12Android自定義ProgressDialog進(jìn)度等待框
這篇文章主要介紹了Android自定義ProgressDialog進(jìn)度等待框,通過本文大家可以嘗試?yán)肁ndroid自定義ProgressDialog,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01詳解Android首選項(xiàng)框架的使用實(shí)例
首選項(xiàng)這個(gè)名詞對(duì)于熟悉Android的朋友們一定不會(huì)感到陌生,它經(jīng)常用來設(shè)置軟件的運(yùn)行參數(shù)。本篇文章主要介紹詳解Android首選項(xiàng)框架的使用實(shí)例,有興趣的可以了解一下。2016-11-11