# 13.基于Http实现网络操作

* 如何用Http库做get请求？
* 如何用Http库做post请求？
* 如何将Response转换成Dart object？
* 如何将请求结果展示在界面上？

网络请求是开发APP必不可少的一部分，比如获取用户订单数据，获取商品列表，提交表单等等都离不了网络请求，那么在Flutter中如何进行网络请求呢？

> Flutter官方推荐我们在Flutter中用Http进行网络请求。

## 什么是Http？

Http是Flutter社区开发的一个可组合的、跨平台的用于Flutter的网络请求插件。

## 如何用http库做get请求？

* 在`pubspec.yaml`中引入[http](https://links.jianshu.com/go?to=https%3A%2F%2Fpub.dartlang.org%2Fpackages%2Fhttp)插件；
* 调用`http.get`发送请求；

```
dependencies:
  http: <latest_version>
```

```
Future<http.Response> fetchPost() {
  return http.get('https://jsonplaceholder.typicode.com/posts/1');
}
```

`http.get()`返回一个包含`http.Response`的`Future`：

* [Future](https://links.jianshu.com/go?to=https%3A%2F%2Fdocs.flutter.io%2Fflutter%2Fdart-async%2FFuture-class.html)：是与异步操作一起工作的核心Dart类。它用于表示未来某个时间可能会出现的可用值或错误；
* `http.Response`：类包含一个成功的HTTP请求接收到的数据；

> 在一节会重点讲解Future的用法，如何从Future中获取服务端具体的返回数据。

## 如何将Response转换成Dart object？

虽然发出网络请求很简单，但如果要使用原始的`Future<http.Response>`并不简单。为了让我们可以开开心心的写代码，我们可以将`http.Response`转换成我们自己的`Dart`对象。

## 创建一个CommonModel类

首先，我们需要创建一个**CommonModel**类，它包含我们网络请求的数据。它还将包括一个工厂构造函数，它允许我们可以通过**json**创建一个**CommonModel**对象。

```
class CommonModel {
  final String icon;
  final String title;
  final String url;
  final String statusBarColor;
  final bool hideAppBar;
  CommonModel({this.icon, this.title, this.url, this.statusBarColor, this.hideAppBar});
  factory CommonModel.fromJson(Map<String, dynamic> json) {
    return CommonModel(
      icon: json['icon'],
      title: json['title'],
      url: json['url'],
      statusBarColor: json['statusBarColor'],
      hideAppBar: json['hideAppBar'],
    );
  }
}
```

将`http.Response`转换成一个`CommonModel`对象

现在，我们将更新`fetchPost`函数以返回一个`Future<Post>`。为此，我们需要：

1. 使用`dart:convert` package将响应内容转化为一个`json`Map；
2. 使用fromJson工厂函数，将json Map 转化为一个CommonModel对象；

```
Future<CommonModel> fetchPost() async {
    final response = await http.get('http://www.devio.org/io/flutter_app/json/test_common_model.json');
    final result = json.decode(response.body);
    return new CommonModel.fromJson(result);
  }
```

## 如何将请求结果展示在界面上？

image

```
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String showResult = '';
  Future<CommonModel> fetchPost() async {
    final response = await http
        .get('http://www.devio.org/io/flutter_app/json/test_common_model.json');
    final result = json.decode(response.body);
    return CommonModel.fromJson(result);
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Http'),
        ),

        body: Column(
          children: <Widget>[
            InkWell(
              onTap: () {
                fetchPost().then((CommonModel value) {
                  setState(() {
                    showResult =
                        '请求结果：\nhideAppBar：{value.hideAppBar}\nicon：{value.icon}';
                  });
                });
              },
              child: Text(
                '点我',
                style: TextStyle(fontSize: 26),
              ),
            ),
            Text(showResult)
          ],
        ),
      ),
    );
  }
}

class CommonModel {
  final String icon;
  final String title;
  final String url;
  final String statusBarColor;
  final bool hideAppBar;
  CommonModel(
      {this.icon, this.title, this.url, this.statusBarColor, this.hideAppBar});
  factory CommonModel.fromJson(Map<String, dynamic> json) {
    return CommonModel(
      icon: json['icon'],
      title: json['title'],
      url: json['url'],
      statusBarColor: json['statusBarColor'],
      hideAppBar: json['hideAppBar'],
    );
  }
}
```

> 在上述代码中我们通过**fetchPost**()**.then**获取**Fluter**的返回结果，其实**Future**可以理解为**ES5**中的**Promise**


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alexcode2.gitbook.io/ios-development-guidelines/flutter/13.-ji-yu-http-shi-xian-wang-luo-cao-zuo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
