0
点赞
收藏
分享

微信扫一扫

第152期:flutter中的网络请求

封面图

第152期:flutter中的网络请求_Flutter

跨平台的http请求

​http​​​包提供了最简单的发起请求的方式,并且这个包在​​WEB​​​,​​ANDROID​​​,​​IOS​​上都得到了很好的支持。

需要注意的是,在某些特定的平台上需要设置一些额外的内容,比如:

在​​ANDROID​​​上必须在manifest(​​AndroidManifest.xml​​)文件中进行声明。

<manifest xmlns:android...>
...
<uses-permission android:name="android.permission.INTERNET" />
<application ...
</manifest>

macOS上必须在​​.entitlements​​进行配置。

<key>com.apple.security.network.client</key>
<true/>

请求数据

从网络上请求数据大致分为四步:

  • 添加​​http​​包
  • 通过​​http​​包发起请求
  • 将收到的响应数据转为客户端可用的数据
  • 展示用户界面

添加​​http​​包

我们只需要在​​pub.dev​​文件中添加配置即可:

dependencies:
http: <latest_version>

然后在代码中导入​​http​​包:

import 'package:http/http.dart' as http;

另外,在安卓中我们需要添加网络权限:

<!-- Required to fetch data from the internet. -->
<uses-permission android:name="android.permission.INTERNET" />

发起请求

发起请求很简单:

Future<http.Response> fetchAlbum() {
return http.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));
}

​http.get()​​​方法返回一个​​Future​​​类的数据,这个数据包含了收到的响应数据。 ​​​Future​​​是用于处理异步操作的核心Dart类。​​Future​​​对象表示将来某个时间可能出现的值或错误。 ​​​http.Response​​类包含从成功的http调用接收的数据。

将响应转为常用对象

虽然发出网络请求很容易,但使用原始的​​Future<http.Response>​​​并不是很方便。为了让我们的开发更简单,我们可以将​​http.Response​​转换为Dart对象。

首先,创建一个包含网络请求数据的​​Album​​类。它包括一个工厂构造函数,用于从JSON创建Album。

class Album {
final int userId;
final int id;
final String title;

const Album({
required this.userId,
required this.id,
required this.title,
});

factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}

然后,我们使用以下步骤更新​​fetchAlbum()​​​函数以返回​​Future<Album>​​:

  • 使用​​dart:Convert​​包将响应体转换为JSON映射。
  • 如果服务器确实返回了状态代码为​​200​​​的OK响应,则使用​​fromJson()​​​工厂方法将JSON映射转换为​​Album​​。
  • 如果服务器没有返回状态代码为200的OK响应,则抛出异常。(即使在“404 Not Found”服务器响应的情况下,也会抛出异常。不要返回null。这在检查快照中的数据时很重要,如下所示。)

Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));

if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}

获取数据

我们可以在​​initState()​​​或​​didChangeDependencies()​​​方法中调用​​fetchAlbum()​​方法。

​initState()​​​方法只调用一次,然后再也不会调用。如果我们想选择重新加载API以响应​​InheritedWidget​​​的更改,我们可以将调用放入​​didChangeDependencies()​​方法中。

class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;

@override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
// ···
}

展示数据

要在屏幕上显示数据,我们可以使用​​FutureBuilder​​​组件。​​FutureBuilder​​组件随Flutter一起提供,可以轻松处理异步数据源。

我们需要提供两个参数:

  • 具体的Future
  • builder方法,用来告诉系统渲染什么内容,根据状态可以选择​​加载中​​等等。

FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}

// By default, show a loading spinner.
return const CircularProgressIndicator();
},
)

为什么要在​​initstate​​中获取数据?

虽然在build()中调用很方便,但不建议将API调用放在build()方法中。

Flutter每次需要更改视图中的任何内容时都会调用​​build()​​​方法,这种情况经常发生。如果将​​fetchAlbum()​​​方法放置在​​build()​​中,则会在每次重建时重复调用,导致应用程序速度减慢。

举报

相关推荐

0 条评论