原文地址: Flutter學習(7)——網路請求框架Dio簡單使用 | Stars-One的雜貨小窩

Flutter系列學習之前都是在個人部落格釋出,感興趣可以過去看看

網路請求一般APP都是需要的,在Flutter中,目前比較流行的網路請求框架是Dio,是Flutter中文網推出的,也算是國人開發的

本文主要是講解如何簡單使用Dio的get請求來獲取資料,並使用Flutter中的listview進行展示

關於listview在之前已經講過使用方法 不清楚的同學可以先去看看Flutter學習(6)——Tab導航與ListView使用 | Stars-One的雜貨小窩

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),
),
],
);
}
}

參考

  • [dio的中文文件](