Flutter&鸿蒙next 封装 Dio 网络请求详解:登录身份验证与免登录缓存

✅近期推荐:求职神器

https://bbs.csdn.net/topics/619384540

🔥欢迎大家订阅系列专栏:flutter_鸿蒙next

💬淼学派语录:只有不断的否认自己和肯定自己,才能走出弯曲不平的泥泞路,因为平坦的大路,太tm无趣了!

写在前面

在现代应用中,处理用户身份验证和缓存是非常重要的。Dio 是一个强大的 Dart HTTP 客户端,支持多种功能,例如请求拦截、响应拦截等。本文将详细讲解如何在 Flutter 中使用 Dio 封装网络请求,并实现登录身份验证及免登录缓存功能。

一、引入 Dio

首先,在 pubspec.yaml 文件中添加 Dio 依赖:

Dart 复制代码
dependencies:
  dio: ^5.0.0
  shared_preferences: ^2.0.0

运行 flutter pub get 命令安装依赖。

二、创建 Dio 封装类

lib/services 目录下新建 network_service.dart 文件,编写以下代码以封装 Dio 功能:

Dart 复制代码
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';

class NetworkService {
  late Dio _dio;
  static const String _tokenKey = 'auth_token';

  NetworkService() {
    _dio = Dio(BaseOptions(
      baseUrl: 'https://api.example.com/', // 替换为你的 API 基础 URL
      connectTimeout: 5000,
      receiveTimeout: 3000,
    ));

    // 添加拦截器
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        final token = await _getToken();
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token'; // 添加 Token 到请求头
        }
        print('请求: ${options.method} ${options.path}');
        handler.next(options);
      },
      onResponse: (response, handler) {
        print('响应: ${response.statusCode} ${response.data}');
        handler.next(response);
      },
      onError: (DioError e, handler) {
        print('错误: ${e.response?.statusCode} ${e.message}');
        handler.next(e);
      },
    ));
  }

  // 获取 Token
  Future<String?> _getToken() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(_tokenKey);
  }

  // 登录请求
  Future<Response> login(String username, String password) async {
    final response = await _dio.post('/login', data: {
      'username': username,
      'password': password,
    });

    // 保存 Token
    await _saveToken(response.data['token']);
    return response;
  }

  // 保存 Token
  Future<void> _saveToken(String token) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_tokenKey, token);
  }

  // 退出登录
  Future<void> logout() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(_tokenKey); // 移除 Token
  }

  // GET 请求
  Future<Response> get(String path, {Map<String, dynamic>? queryParameters}) async {
    return await _dio.get(path, queryParameters: queryParameters);
  }

  // POST 请求
  Future<Response> post(String path, {dynamic data}) async {
    return await _dio.post(path, data: data);
  }
}

代码详解

  1. Token 存储

    • 使用 shared_preferences 存储用户的 Token,以便后续请求中使用。
    • _getToken() 方法用于获取存储的 Token。
  2. 登录请求

    • login 方法发送用户名和密码进行身份验证,成功后保存返回的 Token。
  3. 请求拦截

    • 在请求拦截器中,检查是否有 Token,如果有,则添加到请求头中。
  4. 退出登录

    • logout 方法移除存储的 Token,以实现用户登出。

三、使用封装的 NetworkService

在 Flutter 应用中使用 NetworkService 进行身份验证非常简单。以下示例展示了如何创建一个登录界面。

1. 创建登录界面

lib/main.dart 文件中编写以下代码:

Dart 复制代码
import 'package:flutter/material.dart';
import 'services/network_service.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final NetworkService _networkService = NetworkService();
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  String _message = '';

  void _login() async {
    try {
      final response = await _networkService.login(
        _usernameController.text,
        _passwordController.text,
      );
      setState(() {
        _message = '登录成功: ${response.data}';
      });
    } catch (e) {
      setState(() {
        _message = '登录失败: $e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('登录')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _usernameController,
              decoration: InputDecoration(labelText: '用户名'),
            ),
            TextField(
              controller: _passwordController,
              decoration: InputDecoration(labelText: '密码'),
              obscureText: true,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _login,
              child: Text('登录'),
            ),
            SizedBox(height: 20),
            Text(_message),
          ],
        ),
      ),
    );
  }
}

void main() => runApp(MaterialApp(home: LoginPage()));

代码详解

  • 输入框 :使用 TextField 组件获取用户名和密码。
  • 登录按钮 :点击按钮后调用 _login 方法进行登录。
  • 状态管理 :通过 setState 更新界面,显示登录结果。

写在后面

通过封装 Dio,我们实现了用户身份验证与 Token 的存储和使用。使用 shared_preferences 实现简单的免登录缓存机制,提高用户体验。希望这篇博客能帮助你更好地在 Flutter 中使用 Dio 进行网络请求与身份验证。如有疑问或建议,欢迎讨论!

相关推荐
星释16 分钟前
鸿蒙Flutter实战:30.在Pub上发布鸿蒙化插件
flutter·harmonyos·鸿蒙
前端不太难21 分钟前
鸿蒙游戏 Store 设计(AI + 多端)
人工智能·游戏·harmonyos
nice先生的狂想曲23 分钟前
flutter布局(列表组件)
flutter
见山是山-见水是水24 分钟前
鸿蒙flutter第三方库适配 - 动态工作流
flutter·华为·harmonyos
HwJack2024 分钟前
HarmonyOS 编译产物与包结构小知识
华为·harmonyos
空太Jun28 分钟前
Redis 5大核心数据类型与持久化实战
数据库·redis·缓存
yeziyfx43 分钟前
Flutter SingleChildScrollView内部ListView滑动不了
flutter
Zender Han1 小时前
VS Code 开发 Flutter 常用快捷键和插件工具详解
android·vscode·flutter·ios
于慨1 小时前
flutter安卓调试工具
android·flutter
见山是山-见水是水1 小时前
鸿蒙flutter第三方库适配 - 动态布局库
flutter·华为·harmonyos