Skip to content

HTTP 请求

Flutter 中进行网络请求需要使用第三方包。

安装

bash
flutter pub add http

GET 请求

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

Future<List<User>> fetchUsers() async {
  final response = await http.get(
    Uri.parse('https://jsonplaceholder.typicode.com/users'),
  );

  if (response.statusCode == 200) {
    final List<dynamic> data = json.decode(response.body);
    return data.map((json) => User.fromJson(json)).toList();
  } else {
    throw Exception('请求失败: ${response.statusCode}');
  }
}

POST 请求

dart
Future<User> createUser(String name, String email) async {
  final response = await http.post(
    Uri.parse('https://jsonplaceholder.typicode.com/users'),
    headers: {'Content-Type': 'application/json'},
    body: json.encode({
      'name': name,
      'email': email,
    }),
  );

  if (response.statusCode == 201) {
    return User.fromJson(json.decode(response.body));
  } else {
    throw Exception('创建失败');
  }
}

带状态管理的请求

dart
class UserListPage extends StatefulWidget {
  // ...
}

class _UserListPageState extends State<UserListPage> {
  List<User> _users = [];
  bool _isLoading = true;
  String? _error;

  @override
  void initState() {
    super.initState();
    _loadUsers();
  }

  Future<void> _loadUsers() async {
    try {
      setState(() {
        _isLoading = true;
        _error = null;
      });
      _users = await Api.fetchUsers();
    } catch (e) {
      _error = e.toString();
    } finally {
      setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) return const CircularProgressIndicator();
    if (_error != null) return Text('错误: $_error');
    return ListView.builder(
      itemCount: _users.length,
      itemBuilder: (context, index) => ListTile(
        title: Text(_users[index].name),
      ),
    );
  }
}

带超时和 Header 的请求

dart
final response = await http.get(
  Uri.parse('https://api.example.com/data'),
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer $token',
  },
).timeout(const Duration(seconds: 10));

进阶:dio

当项目需要拦截器、全局配置、文件上传下载、请求取消等能力时,推荐使用 dio 替代 http 包。

http vs dio

特性httpdio
官方包第三方
拦截器
请求取消手动内置
表单/文件上传手动内置
重试机制内置
全局配置BaseOptions
错误类型通用 ExceptionDioException(细分类型)

详见 dio 网络请求

基于 Flutter 官方文档整理