当我们在开发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这个方式里面直接抛出错了,直接就阻断了接下来程序的运行。在修改和排查的时候 都很好确定错误的根源。