当前位置: 首页 > article >正文

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

✅近期推荐:求职神器

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


🔥欢迎大家订阅系列专栏:flutter_鸿蒙next
💬淼学派语录:只有不断的否认自己和肯定自己,才能走出弯曲不平的泥泞路,因为平坦的大路,太tm无趣了!

写在前面

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

一、引入 Dio

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

dependencies:
  dio: ^5.0.0
  shared_preferences: ^2.0.0

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

二、创建 Dio 封装类

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

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 文件中编写以下代码:

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 进行网络请求与身份验证。如有疑问或建议,欢迎讨论!


http://www.kler.cn/a/376203.html

相关文章:

  • 基于YOLO11/v10/v8/v5深度学习的维修工具检测识别系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
  • leetcode hot100【LeetCode 279. 完全平方数】java实现
  • Git 常用命令指南
  • Vue.js 构建可复用的组件
  • 「微服务」持续测试如何做?
  • C++中关于 <functional> 的使用
  • layui tree customSelet选中的内容重写,查找父级
  • Flume的安装配置
  • 服务器文件访问协议
  • go语言回调函数的使用
  • 免杀对抗—反VT沙盒虚拟机反调试进程APC注入
  • LeetCode 3165. 不包含相邻元素的子序列的最大和
  • nginx的基本安装与服务器配置
  • 驱动TFT-1.44寸屏(ST7735)显示器
  • 【面试】数组中 Array.forEach()、Array.map() 遍历结束后是否改变原数组
  • k8s 排查集群中故障节点
  • Jenkins面试整理-如何在 Jenkins 中使用插件?
  • 2000字搞懂Java中Lambda+方法引用简化代码(开发代码量秒缩十倍)
  • 鸿蒙ArkTS中的image组件
  • 代码随想录算法训练营第四十一天 | 01背包问题(二维),01背包问题(一维),416.分割等和子集
  • 分布式和微服务系统区别
  • SpringBoot助力大型商场应急预案自动化
  • C语言日记 2024年11月2日
  • 利士策分享,锚定未来:稳健规划人生
  • git reset 删除错误提交
  • 【Python爬虫实战】网络爬虫完整指南:HTTP/HTTPS协议与爬虫安全实践