flutter-use-http-package
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseImplementing Flutter Networking
实现Flutter网络请求
Contents
目录
Configuration & Permissions
配置与权限
Configure the environment and platform-specific permissions required for network access.
- Add the package dependency via the terminal:
httpbashflutter pub add http - Import the package in your Dart files:
dart
import 'package:http/http.dart' as http; - Configure Android permissions by adding the Internet permission to :
android/app/src/main/AndroidManifest.xmlxml<uses-permission android:name="android.permission.INTERNET" /> - Configure macOS entitlements by adding the network client key to both and
macos/Runner/DebugProfile.entitlements:macos/Runner/Release.entitlementsxml<key>com.apple.security.network.client</key> <true/>
配置网络访问所需的环境和平台特定权限。
- 通过终端添加包依赖:
httpbashflutter pub add http - 在Dart文件中导入该包:
dart
import 'package:http/http.dart' as http; - 配置Android权限,在中添加互联网权限:
android/app/src/main/AndroidManifest.xmlxml<uses-permission android:name="android.permission.INTERNET" /> - 配置macOS权限,在和
macos/Runner/DebugProfile.entitlements中添加网络客户端密钥:macos/Runner/Release.entitlementsxml<key>com.apple.security.network.client</key> <true/>
Request Execution & Response Handling
请求执行与响应处理
Execute HTTP operations and map responses to strongly typed Dart objects.
- URIs: Always parse URL strings using .
Uri.parse('your_url') - Headers: Inject authorization and content-type headers via the parameter map. Use
headersfor auth tokens.HttpHeaders.authorizationHeader - Payloads: For POST and PUT requests, encode the body using from
jsonEncode().dart:convert - Status Validation: Evaluate . Treat
response.statusCode(GET/PUT/DELETE) and200 OK(POST) as success.201 CREATED - Error Handling: Throw explicit exceptions for non-success status codes. Never return on failure, as this prevents
nullfrom triggering its error state and causes infinite loading indicators.FutureBuilder - Deserialization: Parse the raw string using and map it to a custom Dart object using a factory constructor (e.g.,
jsonDecode(response.body)).fromJson
执行HTTP操作并将响应映射为强类型Dart对象。
- URI: 始终使用解析URL字符串。
Uri.parse('your_url') - 请求头: 通过参数注入授权和内容类型请求头。使用
headers处理认证令牌。HttpHeaders.authorizationHeader - 负载: 对于POST和PUT请求,使用中的
dart:convert编码请求体。jsonEncode() - 状态验证: 评估。将
response.statusCode(GET/PUT/DELETE)和200 OK(POST)视为成功状态。201 CREATED - 错误处理: 针对非成功状态码抛出明确的异常。失败时绝不要返回,这会导致
null无法触发错误状态,进而引发无限加载指示器问题。FutureBuilder - 反序列化: 使用解析原始字符串,并通过工厂构造函数(如
jsonDecode(response.body))将其映射为自定义Dart对象。fromJson
Background Parsing
后台解析
Offload expensive JSON parsing to a separate Isolate to prevent UI jank (frame drops).
- Import .
package:flutter/foundation.dart - Use the function to run the parsing logic in a background isolate.
compute() - Ensure the parsing function passed to is a top-level function or a static method, as closures or instance methods cannot be passed across isolates.
compute()
将耗时的JSON解析任务卸载到单独的Isolate中,以避免UI卡顿(掉帧)。
- 导入。
package:flutter/foundation.dart - 使用函数在后台Isolate中运行解析逻辑。
compute() - 确保传递给的解析函数是顶层函数或静态方法,因为闭包或实例方法无法跨Isolate传递。
compute()
Workflow: Executing Network Operations
工作流程:执行网络操作
Use the following checklist to implement and validate network operations.
Task Progress:
- 1. Define the strongly typed Dart model with a factory constructor.
fromJson - 2. Implement the network request method returning a .
Future<Model> - 3. Apply conditional logic based on the operation type:
- If fetching data (GET): Append query parameters to the URI.
- If mutating data (POST/PUT): Set and attach the
'Content-Type': 'application/json; charset=UTF-8'body.jsonEncode - If deleting data (DELETE): Return an empty model instance on success ().
200 OK
- 4. Validate the and throw an
statusCodeon failure.Exception - 5. Integrate the into the UI using
Future.FutureBuilder - 6. Handle ,
snapshot.hasData, and default to asnapshot.hasError.CircularProgressIndicator - 7. Feedback Loop: Run the app -> trigger the network request -> review console for unhandled exceptions -> fix parsing or permission errors.
使用以下清单实现并验证网络操作。
任务进度:
- 1. 定义带有工厂构造函数的强类型Dart模型。
fromJson - 2. 实现返回的网络请求方法。
Future<Model> - 3. 根据操作类型应用条件逻辑:
- 如果是获取数据(GET): 向URI追加查询参数。
- 如果是修改数据(POST/PUT): 设置并附加
'Content-Type': 'application/json; charset=UTF-8'处理后的请求体。jsonEncode - 如果是删除数据(DELETE): 成功时()返回空模型实例。
200 OK
- 4. 验证,失败时抛出
statusCode。Exception - 5. 使用将
FutureBuilder集成到UI中。Future - 6. 处理、
snapshot.hasData状态,默认显示snapshot.hasError。CircularProgressIndicator - 7. 反馈循环: 运行应用 -> 触发网络请求 -> 查看控制台中的未处理异常 -> 修复解析或权限错误。
Examples
示例
High-Fidelity Implementation: Fetching and Parsing in the Background
高保真实现:后台获取与解析
dart
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// 1. Top-level parsing function for Isolate
List<Photo> parsePhotos(String responseBody) {
final parsed = (jsonDecode(responseBody) as List<Object?>)
.cast<Map<String, Object?>>();
return parsed.map<Photo>(Photo.fromJson).toList();
}
// 2. Network execution with background parsing
Future<List<Photo>> fetchPhotos() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/photos'),
headers: {
HttpHeaders.authorizationHeader: 'Bearer your_token_here',
HttpHeaders.acceptHeader: 'application/json',
},
);
if (response.statusCode == 200) {
// Offload heavy parsing to a background isolate
return compute(parsePhotos, response.body);
} else {
throw Exception('Failed to load photos. Status: ${response.statusCode}');
}
}
}
// 3. Strongly typed model
class Photo {
final int id;
final String title;
final String thumbnailUrl;
const Photo({
required this.id,
required this.title,
required this.thumbnailUrl,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
id: json['id'] as int,
title: json['title'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
);
}
}
// 4. UI Integration
class PhotoGallery extends StatefulWidget {
const PhotoGallery({super.key});
State<PhotoGallery> createState() => _PhotoGalleryState();
}
class _PhotoGalleryState extends State<PhotoGallery> {
late Future<List<Photo>> _futurePhotos;
void initState() {
super.initState();
// Initialize Future once to prevent re-fetching on rebuilds
_futurePhotos = fetchPhotos();
}
Widget build(BuildContext context) {
return FutureBuilder<List<Photo>>(
future: _futurePhotos,
builder: (context, snapshot) {
if (snapshot.hasData) {
final photos = snapshot.data!;
return ListView.builder(
itemCount: photos.length,
itemBuilder: (context, index) => ListTile(
leading: Image.network(photos[index].thumbnailUrl),
title: Text(photos[index].title),
),
);
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
// Default loading state
return const Center(child: CircularProgressIndicator());
},
);
}
}dart
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// 1. 用于Isolate的顶层解析函数
List<Photo> parsePhotos(String responseBody) {
final parsed = (jsonDecode(responseBody) as List<Object?>)
.cast<Map<String, Object?>>();
return parsed.map<Photo>(Photo.fromJson).toList();
}
// 2. 带后台解析的网络执行
Future<List<Photo>> fetchPhotos() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/photos'),
headers: {
HttpHeaders.authorizationHeader: 'Bearer your_token_here',
HttpHeaders.acceptHeader: 'application/json',
},
);
if (response.statusCode == 200) {
// 将繁重的解析任务卸载到后台Isolate
return compute(parsePhotos, response.body);
} else {
throw Exception('Failed to load photos. Status: ${response.statusCode}');
}
}
}
// 3. 强类型模型
class Photo {
final int id;
final String title;
final String thumbnailUrl;
const Photo({
required this.id,
required this.title,
required this.thumbnailUrl,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
id: json['id'] as int,
title: json['title'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
);
}
}
// 4. UI集成
class PhotoGallery extends StatefulWidget {
const PhotoGallery({super.key});
State<PhotoGallery> createState() => _PhotoGalleryState();
}
class _PhotoGalleryState extends State<PhotoGallery> {
late Future<List<Photo>> _futurePhotos;
void initState() {
super.initState();
// 初始化Future一次,避免重建时重新请求
_futurePhotos = fetchPhotos();
}
Widget build(BuildContext context) {
return FutureBuilder<List<Photo>>(
future: _futurePhotos,
builder: (context, snapshot) {
if (snapshot.hasData) {
final photos = snapshot.data!;
return ListView.builder(
itemCount: photos.length,
itemBuilder: (context, index) => ListTile(
leading: Image.network(photos[index].thumbnailUrl),
title: Text(photos[index].title),
),
);
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
// 默认加载状态
return const Center(child: CircularProgressIndicator());
},
);
}
}