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、手机号、身份证、详细地址。网络日志要能辅助排错,但不能泄露用户数据。
不需要翻每个页面。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐