当我们在开发Flutter的时候,肯定会和后端接口对接去请求后端的数据,那么本次我们将,讲解Flutter如何请求数据,以及如何封装返回结果。
话不多说直接上代码,首先根据Flutter官方网站的描述,需要在pubspec.yaml引入一个http库这样就能够发送http请求了。
step1:
#pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
http: ^0.13.3
step2:
//引入
import 'dart:convert';
import 'package:http/http.dart' as http;
class HttpService {
final String appKey = ''
//这里以请求阿里地图地理位置逆编码为例
Future baseLatLongGetLocationString(latlong) async {
String url =
'https://restapi.amap.com/v3/geocode/regeo?output=json&location=${latlong}&key=${key}&radius=1000&extensions=base';
var res = await http.post(Uri.parse(url));
//查看返回状态
if (res.statusCode == 200) {
var body = json.decode(res.body);
return body;
} else {
return null;
}
}
如上所示代码就是完整的发送一个get请求的过程,把返回的body直接放入json.decode(res.body)进行解析是没有问题这,这样就会返回一个map对象。同时dart通过Future特性和async关键字来实现异步操作。
同时发送post请求和发送get请求还不一样,发送post请求的时候请求参数不能这样传递,我们一般会:
//发送post请求
Future baseLatLongGetLocationString(body,url) async {
//其中 body是请求的请求体 就是请求包含的参数
//url就是需要请求的url
var res = await http.post(Uri.parse(url), body: json.decode(body), headers: {});
if (res.statusCode == 200) {
var body = json.decode(res.body);
return body;
} else {
return null;
}
我们能够明显看出使用get和post请求的方式是不一样的。
当然如果是一个简单的项目这样做是完全可行的,并且也是最简单的操作,但是当项目的复杂度上升之后,就这样把返回值返回明显会有一个问题,那么就是空指针异常,设想以下如果我们请求的数据字段很多,这个时候如果还是用返回的这个map,代码会写的非常的乱,并且没有头绪,出了错也不知道如何排错,所以我们通过面向对象的方式对返回数据进行封装。
如下所示当返回的json数据是这个样的
{
ok:true,
UserInfo:[
{
name:'张三',
passowrd:'111'
},
{
name:'李四',
passowrd:'222'
},{
password:'333'
}
]
}
我们如果直接将把userInfo数据返回供视图层进行进行展示,取值方式就会是这样的,很明显name3
会报错,空指针,当改只有一个页面使用这个数据的时候,对问题进行查找和修改会很方便,但是如果有很多的页面都会使用这个数据,这个时候对问题进行查找和修改就不是很方便了。
name1 = userInfo[0]['name]
name2 = userInfo[1]['name]
name3 = userInfo[2]['name]
那么我们通过将返回数据封装成dart里面的class的方式,这样就能很轻松的解决这个工程性问题:
如下所示:
class User{
String? name;
String? password;
User({this.name,this.password});
User.fromJson(Map<String, dynamic> json){
name = json['name'];
password = json['password'];
}
}
那么Http请求返回值就会转化为这个样子:
class User{
String? name;
String? password;
User({this.name,this.password});
User.fromJson(Map<String, dynamic> json){
name = json['name'];
password = json['password'];
}
}
class UserInfo{
bool? ok;
List<User>? userInfos = [];
UserInfo.fromJson(Map<String, dynamic> json){
json['UserInfo'].forEach((v) {
userInfos!.add(User.fromJson(v));
});
}
}
//发送post请求
Future userInfoRequest(body,url) async {
//其中 body是请求的请求体 就是请求包含的参数
//url就是需要请求的url
var res = await http.post(Uri.parse(url), body: json.decode(body), headers: {});
if (res.statusCode == 200) {
var body = json.decode(res.body);
return UserInfo.fromJson( body);
} else {
return null;
}
如上所示通过上述方法就能实现请求值的封装,这样的好处是如果出现空指针异常,这个错误会在请求的时候直接报出来,在userInforRequest这个方式里面直接抛出错了,直接就阻断了接下来程序的运行。在修改和排查的时候 都很好确定错误的根源。