09-Flutter鸿蒙网络请求入门:HTTP数据请求和JSON模型封装
·
09. Flutter鸿蒙网络请求入门:HTTP数据请求和JSON模型封装

网络请求是业务项目最常见的能力之一。Flutter 鸿蒙项目中,普通 HTTP 请求仍然可以在 Flutter 层完成:添加依赖、封装模型、写请求服务、处理加载状态和错误状态即可。

添加依赖
dependencies:
flutter:
sdk: flutter
http: ^1.2.2
执行:
flutter pub get
定义模型
class User {
final int id;
final String name;
final String phone;
const User({
required this.id,
required this.name,
required this.phone,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] as int? ?? 0,
name: json['name'] as String? ?? '',
phone: json['phone'] as String? ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'phone': phone,
};
}
}
封装服务
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
ApiService({http.Client? client}) : _client = client ?? http.Client();
final http.Client _client;
static const String baseUrl = 'https://example.com/api';
Future<List<User>> fetchUsers() async {
final uri = Uri.parse('$baseUrl/users');
final response = await _client.get(uri);
if (response.statusCode != 200) {
throw Exception('请求失败:${response.statusCode}');
}
final data = jsonDecode(response.body);
if (data is! List) {
throw Exception('接口返回格式不是数组');
}
return data
.map((item) => User.fromJson(item as Map<String, dynamic>))
.toList();
}
Future<User> createUser(String name, String phone) async {
final uri = Uri.parse('$baseUrl/users');
final response = await _client.post(
uri,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'name': name, 'phone': phone}),
);
if (response.statusCode != 200 && response.statusCode != 201) {
throw Exception('新增失败:${response.statusCode}');
}
return User.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
}
}
页面状态
class UserListPage extends StatefulWidget {
const UserListPage({super.key});
State<UserListPage> createState() => _UserListPageState();
}
class _UserListPageState extends State<UserListPage> {
late Future<List<User>> _future;
void initState() {
super.initState();
_future = ApiService().fetchUsers();
}
Future<void> _reload() async {
setState(() {
_future = ApiService().fetchUsers();
});
}
Widget build(BuildContext context) {
return FutureBuilder<List<User>>(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('加载失败:${snapshot.error}'),
const SizedBox(height: 12),
FilledButton(onPressed: _reload, child: const Text('重试')),
],
),
);
}
final users = snapshot.data ?? [];
if (users.isEmpty) {
return const Center(child: Text('暂无数据'));
}
return RefreshIndicator(
onRefresh: _reload,
child: ListView.builder(
itemCount: users.length,
itemBuilder: (_, index) {
final user = users[index];
return ListTile(
title: Text(user.name),
subtitle: Text(user.phone),
);
},
),
);
},
);
}
}
排错

网络问题常见排查:
1. 接口地址是否能在浏览器或 Postman 打开
2. 设备是否有网络权限和网络连接
3. HTTP/HTTPS 是否符合服务端要求
4. JSON 顶层结构是对象还是数组
5. statusCode 是否被正确处理
6. 页面是否处理 loading、empty、error 三种状态
请求层不要直接写在页面里
页面里直接写 http.get 能跑,但项目变大后很难维护。更好的做法是页面只关心状态,网络细节放到 service:
lib
├─ models
│ └─ user.dart
├─ services
│ └─ api_service.dart
└─ pages
└─ user_list_page.dart
这样接口地址变化、请求头变化、错误处理变化时,不需要翻每个页面。
调试接口返回
开发阶段可以临时打印响应:
debugPrint('statusCode: ${response.statusCode}');
debugPrint('body: ${response.body}');
正式提交前不要在日志里输出敏感信息,比如 token、手机号、身份证、详细地址。网络日志要能辅助排错,但不能泄露用户数据。
不需要翻每个页面。
更多推荐




所有评论(0)