前言
Flutter是Google開源的構(gòu)建用戶界面(UI)工具包,幫助開發(fā)者通過一套代碼庫高效構(gòu)建多平臺(tái)精美應(yīng)用,支持移動(dòng)、Web、桌面和嵌入式平臺(tái)。Flutter 開源、免費(fèi),擁有寬松的開源協(xié)議,適合商業(yè)項(xiàng)目。目前,Flutter已推出穩(wěn)定的2.0版本。也是目前最火的跨平臺(tái)開發(fā)工具之一

Dart支持的API請(qǐng)求
之前在Dart語言的學(xué)習(xí)中,我們直接可以很方便的使用Dart支持的網(wǎng)絡(luò)請(qǐng)求,在Flutter中也一樣,直接這樣就可以獲取數(shù)據(jù)源并將其進(jìn)行展示
readData() async {
HttpClientResponse response = await getBaiduData();
String res = await response.transform(utf8.decoder).join();
setState(() {
data = res;
});
}
getBaiduData() async {
HttpClient client = HttpClient();
var request = await client.getUrl(Uri.http("www.baidu.com", ""));
var response = await request.close();
return response;
}
Http庫
Http庫也是我們常用的網(wǎng)絡(luò)請(qǐng)求框架
添加依賴
http: ^0.12.2
https://github.com/dart-lang/http
數(shù)據(jù)請(qǐng)求與展示
class HomePageStates extends State<HomePage>
with SingleTickerProviderStateMixin {
String data = "";
bool isShowLoading = false;
@override
void initState() {
super.initState();
}
getData() async {
setState(() {
isShowLoading = true;
});
var http = Client();
Response response = await http.get("https://jsonplaceholder.typicode.com/todos/1");
setState(() {
data = response.body;
isShowLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
centerTitle: true,
),
body: Stack(
children: [
Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$data'),
Ink(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20)),
child: InkWell(
borderRadius: BorderRadius.circular(20),
onTap: () {
getData();
},
splashColor: Colors.white,
child: Container(
width: 100,
height: 40,
alignment: Alignment.center,
child: Text(
'Get',
style: TextStyle(color: Colors.white),
),
),
),
),
],
),
),
Visibility(
visible: isShowLoading,
child: Container(
alignment: Alignment.center,
child: Container(
width: double.maxFinite,
height: double.maxFinite,
child: Center(
child: SizedBox(
height: 40,
width: 40,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
),
),
),
),
))
],
));
}
}

dio
dio庫是一個(gè)更強(qiáng)大的網(wǎng)絡(luò)請(qǐng)求框架,支持更多的網(wǎng)絡(luò)請(qǐng)求設(shè)置,攔截器,超時(shí),Cookie,文傳等各種設(shè)置
https://github.com/flutterchina/dio
添加依賴
dio: ^4.0.1
發(fā)起一個(gè)簡(jiǎn)單的請(qǐng)求
getData() async {
setState(() {
isShowLoading = true;
});
var dio = Dio();
var response =
await dio.get("https://jsonplaceholder.typicode.com/todos/1");
data = response.data.toString();
setState(() {
data = response.data.toString();
isShowLoading = false;
});
}

添加一個(gè)異常處理
當(dāng)訪問出現(xiàn)異常時(shí),比如資源訪問失敗,訪問超時(shí)等
這里由于使用了await 的同步調(diào)用,所以需要使用try catch進(jìn)行異常捕獲,當(dāng)api調(diào)用失敗時(shí)會(huì)返回DioError里面封裝了錯(cuò)誤狀態(tài)碼,錯(cuò)誤信息,以及錯(cuò)誤類型DioErrorType 用于做判斷
enum DioErrorType {
/// It occurs when url is opened timeout.
connectTimeout,
/// It occurs when url is sent timeout.
sendTimeout,
///It occurs when receiving timeout.
receiveTimeout,
/// When the server response, but with a incorrect status, such as 404, 503...
response,
/// When the request is cancelled, dio will throw a error with this type.
cancel,
/// Default error type, Some other Error. In this case, you can
/// use the DioError.error if it is not null.
other,
}
這里我使用錯(cuò)誤的鏈接訪問
getData() async {
setState(() {
isShowLoading = true;
});
try {
var dio = Dio();
var response =
await dio.get("https://jsonplaceholder.typicode.com/todos/1test");
data = response.data.toString();
} on DioError catch (e) {
data =
"error ${e.type}---${e.response?.statusCode}---${e.response?.statusMessage}";
} catch (e) {
//other exception
data = "other error ${e.toString()}";
} finally {
setState(() {
isShowLoading = false;
});
}
}

訪問超時(shí)處理
某些時(shí)候當(dāng)服務(wù)不穩(wěn)定時(shí),會(huì)導(dǎo)致請(qǐng)求時(shí)間過長(zhǎng),可以設(shè)置api的請(qǐng)求超時(shí)時(shí)間,這里為了測(cè)試我們?cè)O(shè)置1毫秒的超時(shí)時(shí)間
var dio = Dio(BaseOptions(receiveTimeout: 1,connectTimeout: 1,sendTimeout: 1));

添加攔截器
攔截器是API請(qǐng)求的很重要一部分,我們可以全局?jǐn)r截發(fā)出去的請(qǐng)求數(shù)據(jù)比如為其添加特殊的Header,或者可以攔截返回的數(shù)據(jù)信息用來做一些公共處理或者打印日志
添加庫提供的日志攔截器,方便我們進(jìn)行請(qǐng)求調(diào)試
var dio = Dio(BaseOptions(receiveTimeout: 10000,connectTimeout: 10000,sendTimeout: 10000)).interceptors.add(LogInterceptor());
也可以自定義攔截器,將請(qǐng)求的額鏈接替換到https://jsonplaceholder.typicode.com/todos/2
dio.interceptors.add(InterceptorsWrapper(onRequest: (options,handler){
options.headers['from'] = 'Mike_Test';
options.path = "https://jsonplaceholder.typicode.com/todos/2";
handler.next(options);
}));
數(shù)據(jù)轉(zhuǎn)換
通常情況下我們會(huì)將API返回的Jason數(shù)據(jù)轉(zhuǎn)換為我們的實(shí)體類,這樣會(huì)方便我們獲取其中的字段用于設(shè)置和使用
var maps = json.decode("{\"id\":\"2\"}");
var model = ResponseModel(maps["id"]);
print(model.id);
也可以直接安裝插件JsonToDart去創(chuàng)建對(duì)應(yīng)的實(shí)體類,這樣也避免手動(dòng)寫字符串的風(fēng)險(xiǎn)
https://plugins.jetbrains.com/plugin/12562-jsontodart-json-to-dart-
/// id : "2"
class ResponseModel {
ResponseModel({
required String id,}){
_id = id;
}
ResponseModel.fromJson(dynamic json) {
_id = json['id'];
}
String _id ="";
String get id => _id;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = _id;
return map;
}
}
var model = ResponseModel.fromJson(json.decode("{\"id\":\"2\"}"));
print('${model.id}');
歡迎關(guān)注Mike的簡(jiǎn)書
Android 知識(shí)整理