前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter lesson 9: Flutter的网络(HTTP)请求

Flutter lesson 9: Flutter的网络(HTTP)请求

作者头像
踏浪
发布2019-07-31 11:40:32
2.5K0
发布2019-07-31 11:40:32
举报
文章被收录于专栏:踏浪的文章踏浪的文章

Flutter中网络请求有两种,一个是使用Flutter自带的网络请求,另一种则是使用第三方HTTP请求插件dio

Flutter中自带的HTTP请求

如果要使用Flutter自带的HTTP请求,需要引入下面两个库

代码语言:javascript
复制
import 'dart:io';
import 'dart:convert';

dart:io 用于发起http请求。这个库里面才有 HttpClient

代码语言:javascript
复制
var httpClient = new HttpClient();

因为网络请求需要时间,我们需要在网络请求成功后在来更新数据,所以,我们需要使用到异步。Flutter 官网建议我们使用 async/await 来进行处理异步(借鉴了前端中的ES7的异步处理)。

使用Flutter自带的HTTP请求一般包含以下几个步骤:

  1. 创建 client。 new HttpClient(),这个对象下面有许多方法,get,post等等。见下图
HttpClient 对象
HttpClient 对象
  1. 构造 Uri。不同于前端(HTML)的网页请求,直接一个 URL 链接就可以了。在Flutter中,请求需要使用 Uri 而不是 Url。关于 URL 与 URI 的区别,可以HTTP 协议中 URI 和 URL 有什么区别?
  2. 发起请求,等待请求,同时您也可以配置请求的headers,body等等。
  3. 关闭请求。等待响应。
  4. 解码响应的内容。

看看下面的代码,代码来源于Flutter中文网

代码语言:javascript
复制
get() async {
  var httpClient = new HttpClient();
  var uri = new Uri.http(
      'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
  var request = await httpClient.getUrl(uri);
  var response = await request.close();
  var responseBody = await response.transform(utf8.decoder).join();
}

因为在请求中,返回的数据一般都是 JSON 格式的数据,但是在Flutter中不能直接拿出来就用,这里需要转一下,这时候就需要用到 dart:convert

使用dart:convert库可以简单解码和编码JSON。 有关其他的JSON文档,请参阅JSON和序列化

看看最后的代码,下面两个都是get,使用了不同的方式,第二个还带了参数。如果要使用post或者其他请求,可以自己尝试

代码语言:javascript
复制
import 'dart:io';
import 'dart:convert';

import 'package:flutter/material.dart';

void main() => runApp(LocaleHttp());

class LocaleHttp extends StatefulWidget {
  LocaleHttp({Key key}) : super(key: key);

  _LocaleHttpState createState() => _LocaleHttpState();
}

class _LocaleHttpState extends State<LocaleHttp> {
  var data;
  Map _person = {
    "name": "点击按钮开始请求",
    "joinTime": "点击按钮开始请求",
    "email": "点击按钮开始请求"
  };


  _getData() async {
    var url = "http://rap2api.taobao.org/app/mock/162174/common/content";
    var httpClient = new HttpClient();

    String result;
    try {
      var request = await httpClient.getUrl(Uri.parse(url));
      var response = await request.close();
      // 上面的两个一步执行完成后在来执行下面的判断
      if( response.statusCode == HttpStatus.ok ) {
        // 如果返回的状态是 200 那么请求成功
        var json = await response.transform(utf8.decoder).join();
        var data = jsonDecode(json);
        result = data['data'][0]["description"];
      }
    } catch(err) {
      result = "Some Error";
    }
    
    setState(() {
      data = result;
    });
  }

  _getPerson() async {
    var httpClient = new HttpClient();
    var uri = new Uri.http('rap2api.taobao.org', "app/mock/162174/common/get-test", {
      "id": "1"
    });

    Map result = new Map();
    setState(() {
      _person = {
        "name": "请求中",
        "joinTime": "请求中",
        "email": "请求中"
      };
    });
    try {
      var request = await httpClient.getUrl(uri);
      var response = await request.close();
      // 上面的两个一步执行完成后在来执行下面的判断
      if( response.statusCode == HttpStatus.ok ) {
        // 如果返回的状态是 200 那么请求成功
        // 将返回的数据转一次格式,下面一行代码写法可以固定了
        var json = await response.transform(utf8.decoder).join();
        var data = jsonDecode(json)["res"];
        result = data;
      }
    } catch(err) {
      result = {
        "name": "请求失败",
        "joinTime": "请求失败",
        "email": "请求失败"
      };
    }
    
    setState(() {
      _person = result;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          RaisedButton(
            child: Text('获取数据'),
            onPressed: _getData,
          ),
          Text(data == null ? "空" : data),
          RaisedButton(
            child: Text('获取人物信息'),
            onPressed: _getPerson,
          ),
          Text(_person["name"]),
          Text(_person["joinTime"]),
          Text(_person["email"]),
        ],
      ),
    );
  }
}

上面的代码中用到了 Map 对象,注意注意的是 Map 中的对象的每一个字段的值在最开始如果已经确定好了(比如都是字符串),在后面 setState 中,如果返回的数据中有其他的数据类型(比如 number ),那这个时候你在设置的时候就会报错 type int is not a subtype of type "String"。或者你会遇到其他的错误,这个不会像在 JavaScript 中那样随意。

使用 dio

使用 dio 需要修安装 dio 插件,当前我使用的是最新的版本 2.1.11

代码语言:javascript
复制
dependencies:
  flutter:
    sdk: flutter
  flutter_webview_plugin: ^0.3.5
  image_picker: 0.6.0+9
  fluttertoast: ^3.1.0
  dio: 2.1.11

dio 具体的时候方法可以去 dio-github 上面查看,很简单,这里就不做过多说明。总之,相比于原生的 HTTP 请求,dio可谓是方便实用了需要,从下面的代码中就可以看出来。就绪在前端中,原生的 XMLHttpRequest几乎看不见,实际开发用的基本都是 axios 一样。

代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

void main() => runApp(DioHttp());

class DioHttp extends StatefulWidget {
  DioHttp({Key key}) : super(key: key);

  _DioHttpState createState() => _DioHttpState();
}

class _DioHttpState extends State<DioHttp> {
  var data;
  Map _person = {
    "name": "点击按钮开始请求",
    "sex": -1,
    "joinTime": "点击按钮开始请求",
    "email": "点击按钮开始请求"
  };


  _getData() async {
    var url = "http://rap2api.taobao.org/app/mock/162174/common/content";
    Dio dio = new Dio();

    String result;
    try {
      Response response = await dio.get(url);
      print(response.data["data"]);
      // 不要使用 response.data.data[0].description 这样的形势,获取不到
      result = response.data["data"][0]["description"];
    } catch(err) {
      result = "Some Error";
    }
    
    setState(() {
      data = result;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          RaisedButton(
            child: Text('获取数据'),
            onPressed: _getData,
          ),
          Text(data == null ? "空" : data)
        ],
      ),
    );
  }
}

具体的App的源码地址

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Flutter中自带的HTTP请求
  • 使用 dio
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档