原文地址: Flutter學習(7)——網路請求框架Dio簡單使用 | Stars-One的雜貨小窩
之前的Flutter學習系列都是在個人部落格上釋出的,感興趣可以去看看,就不搬過來了
網路請求一般APP都是需要的,在Flutter中,目前比較流行的網路請求框架是Dio,是Flutter中文網推出的,也算是國人開發的?
本文主要是講解如何簡單使用Dio的get請求來獲取資料,並使用Flutter中的listview進行展示
關於listview在之前已經講過使用方法? 不清楚的同學可以先去看看Flutter學習(6)——Tab導航與ListView使用 | Stars-One的雜貨小窩
注: 本文基於Fluter1.2版本,只講解了Dio的get請求,之後再看看有沒有時間補充一波詳細的使用和例子吧
Dio介紹
dio是一個強大的Dart Http請求庫,支援Restful API、FormData、攔截器、請求取消、Cookie管理、檔案上傳/下載、超時、自定義介面卡等...
實現過程
1.get請求資料
這裡,我們使用最為簡單的get請求方式來獲取資料,介面的話我們使用郭霖大佬提供的API介面http://guolin.tech/api/china,我們可以使用瀏覽器直接訪問,來看看獲取的資料,如下圖所示
返回的資料是各大城市的相關資料,待會我們可以使用列表把城市名顯示出來即可
請求介面的程式碼如下
void getCityData() async {
Response response;
var dio = Dio();
response = await dio.get('http://guolin.tech/api/china');
print(response.data.toString());
}
因為這裡是資料是從介面獲取的,資料為動態的,這裡我們的頁面得使用StatefulWidget,則是在State類初始化initState
方法的時候呼叫介面
程式碼跑起來,進到頁面,發現報錯了? 錯誤如下所示:
百度一看,是因為Android高版本不支援http協議的緣故,所以,按照之前的老套路,加個xml配置,調整即可,具體可參考Android 9 網路請求失敗 | Stars-One的雜貨小窩
按照上面的步驟配置後,再來試下(注意需要停止APP後重新進行編譯,然後再點debug或run的圖示,使用熱過載是不會起作用的)
ok,成功調通,資料已經列印出來了:happy:
2.實體類建立
之前我們Android開發的時候,使用的是Gson解析json字串,將json字串轉為對應的實體類,好方便我們取值,這裡,flutter同樣也是
這裡推薦使用個外掛JsonToDart
進行實體類的生成,外掛地址
安裝好外掛後,我們要使用的話,可以右鍵,然後懸著具體選單即可新建即可,這裡我是建了個model
資料夾,右鍵model
資料夾, New -> Json To Dart
把json字串輸入進去,輸入類名,之後點選Generate
即可生成一個dart的實體類檔案
以往Android開發中我們是使用Gson等框架,把json字串轉為實體類
而在flutter中,由於其內建有Json型別的資料,所以不必要再引入其他框架,使用jsonDecode
方法即可
小提示:如果直接複製,
jsonDecode
可能會報錯,因為還沒有匯入,可以游標選擇jsonDecode,按下alt+enter
,選擇import開頭的那個選單即可自動匯入
我們稍微改下程式碼,如下:
void getCityData() async {
Response response;
var dio = Dio();
response = await dio.get('http://guolin.tech/api/china',options: Options(responseType: ResponseType.plain));
var list = jsonDecode(response.data);
var cityList = list.map((m) => new CityModel.fromJson(m)).toList();
print(cityList);
}
這裡我們可以看到程式碼的第五行,傳了個options引數,options是為了設定返回的型別資料,如果沒有這個的話,Dio會自動將返回的資料轉為Json型別的物件
但是由於現在介面返回的一個Json陣列的字串,導致無法解析成功(平常介面都是一個json的字串,郭霖大佬寫得..? )
所以得采用此方法進行解析,之後將資料轉為List型別,裡面的每個資料都是實體類
3.列表展示
展示就比較簡單了,我們使用ListView即可,不過,需要注意的是,得提前在State類中定義好一個List陣列
介面請求到資料之後,更新此List陣列裡的資料即可達到更改UI的操作(注意使用setState()
方法哦?)
void getCityData() async {
var dio = Dio();
Response response = await dio.get('http://guolin.tech/api/china',
options: Options(responseType: ResponseType.plain));
var list = jsonDecode(response.data);
var cityList = list.map((m) => new CityModel.fromJson(m)).toList();
//注意使用setState方法
setState(() {
//this.list是在State類中定義的
this.list.addAll(cityList);
});
}
效果圖
原始碼
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_demo/model/city_model.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'MyMaterialPage.dart';
class DioTestPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return DioTestState();
}
}
class DioTestState extends State<DioTestPage> {
List list = [];
@override
Widget build(BuildContext context) {
return MyMaterialPage("Dio獲取資料及展示", _listView());
}
@override
void initState() {
getCityData();
}
void getCityData() async {
var dio = Dio();
Response response = await dio.get('http://guolin.tech/api/china',
options: Options(responseType: ResponseType.plain));
var list = jsonDecode(response.data);
var cityList =
list.map((m) => new CityModel.fromJson(m)).toList();
setState(() {
this.list.addAll(cityList);
});
}
Widget _listView() {
return new ListView.builder(
//listview的子項item數量
itemCount: list.length,
//內邊距
padding: new EdgeInsets.all(5.0),
itemBuilder: (BuildContext context, int index) {
//返回每個子項item的widget
//城市名
return _listItemView(list[index].name);
},
);
}
Widget _listItemView(String name) {
return Row(
children: [
Center(
child: Text(name),
),
],
);
}
}