原文地址: 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請求,之后再看看有沒有時間補充一波詳細的使用和例子吧,本篇代碼保存在github
Dio介紹
dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等...
實現過程
PS:引入Dio框架,我們只需要在
pubspec.yaml
文件中的dependencies
標簽下面寫即可
dio: ^3.0.0
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),
),
],
);
}
}