Flutter Deer网络拦截器设计:Token刷新与错误处理

Flutter Deer网络拦截器设计:Token刷新与错误处理

【免费下载链接】flutter_deer 🦌 Flutter 练习项目(包括集成测试、可访问性测试)。内含完整UI设计图,更贴近真实项目的练习。Flutter practice project (including integration testing and a***essibility testing). Contains ***plete UI design drawings for a more realistic practice project. 项目地址: https://gitcode.***/gh_mirrors/fl/flutter_deer

在移动应用开发中,网络请求的拦截与处理是保障应用稳定性和用户体验的关键环节。Flutter Deer作为一个贴近真实项目的练习项目,其网络层设计包含了完整的拦截器实现,本文将深入解析其Token刷新机制与错误处理策略。

拦截器架构概览

Flutter Deer采用Dio作为网络请求库,通过多层拦截器实现请求处理的解耦。项目中主要实现了四种拦截器,分别负责认证、Token刷新、日志记录和数据适配,形成了完整的请求处理流水线。

拦截器实现类

项目的拦截器实现集中在lib/***/intercept.dart文件中,包含以下核心类:

  • AuthInterceptor:处理请求认证信息,如添加Token头
  • TokenInterceptor:实现Token过期自动刷新逻辑
  • LoggingInterceptor:打印请求日志,辅助调试
  • AdapterInterceptor:统一数据格式,适配后端返回

Token刷新机制

Token过期是常见的身份验证问题,Flutter Deer通过TokenInterceptor实现了自动化的Token刷新流程,避免用户频繁登录。

刷新流程设计

Token刷新的核心逻辑在TokenInterceptor类中实现,当检测到401状态码时触发刷新机制:

@override
Future<void> onResponse(Response<dynamic> response, ResponseInterceptorHandler handler) async {
  //401代表token过期
  if (response.statusCode == ExceptionHandle.unauthorized) {
    Log.d('-----------自动刷新Token------------');
    final String? a***essToken = await getToken(); // 获取新的a***essToken
    Log.e('-----------NewToken: $a***essToken ------------');
    SpUtil.putString(Constant.a***essToken, a***essToken.nullSafe);

    if (a***essToken != null) {
      // 重新请求失败接口
      final RequestOptions request = response.requestOptions;
      request.headers['Authorization'] = 'Bearer $a***essToken';
      
      // 重新发起请求的实现...
    }
  }
  super.onResponse(response, handler);
}

Token存储与获取

项目使用sp_util存储Token信息,定义在lib/res/constant.dart中的常量:

class Constant {
  static const String a***essToken = 'a***ess_token';
  static const String refreshToken = 'refresh_token';
  // 其他常量定义...
}

Token的获取通过getToken()方法实现,该方法会调用刷新Token的API:

Future<String?> getToken() async {
  final Map<String, String> params = <String, String>{};
  params['refresh_token'] = SpUtil.getString(Constant.refreshToken).nullSafe;
  try {
    _tokenDio ??= Dio();
    _tokenDio!.options = DioUtils.instance.dio.options;
    final Response<dynamic> response = await _tokenDio!.post<dynamic>('lgn/refreshToken', data: params);
    if (response.statusCode == ExceptionHandle.su***ess) {
      return (json.decode(response.data.toString()) as Map<String, dynamic>)['a***ess_token'] as String;
    }
  } catch(e) {
    Log.e('刷新Token失败!');
  }
  return null;
}

请求认证处理

AuthInterceptor负责为每个请求添加认证头,确保API调用的合法性:

class AuthInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    final String a***essToken = SpUtil.getString(Constant.a***essToken).nullSafe;
    if (a***essToken.isNotEmpty) {
      options.headers['Authorization'] = 'token $a***essToken';
    }
    if (!Device.isWeb) {
      // 添加User-Agent头,符合GitHub API要求
      options.headers['User-Agent'] = 'Mozilla/5.0';
    }
    super.onRequest(options, handler);
  }
}

错误处理策略

错误处理是网络请求中不可或缺的一环,Flutter Deer通过AdapterInterceptor和全局异常处理实现了统一的错误管理。

数据适配与错误格式化

AdapterInterceptor将不同格式的后端响应统一转换为应用内部标准格式:

Response<dynamic> adapterData(Response<dynamic> response) {
  String result;
  String content = response.data?.toString() ?? '';
  
  // 成功状态处理
  if (response.statusCode == ExceptionHandle.su***ess || response.statusCode == ExceptionHandle.su***ess_not_content) {
    // 格式化成功响应...
  } else {
    // 错误状态处理...
    if (response.statusCode == ExceptionHandle.not_found) {
      result = sprintf(_kFailureFormat, [response.statusCode, _kNotFound]);
      response.statusCode = ExceptionHandle.su***ess;
    } else {
      // 其他错误处理...
    }
  }
  response.data = result;
  return response;
}

异常处理工具类

项目定义了lib/***/error_handle.dart文件,统一管理异常类型和错误码:

class ExceptionHandle {
  static const int su***ess = 200;
  static const int su***ess_not_content = 204;
  static const int unauthorized = 401;
  static const int not_found = 404;
  
  // 其他错误码定义...
  
  static String handleException(dynamic e) {
    // 异常处理逻辑...
  }
}

日志拦截器

LoggingInterceptor实现了请求日志的打印,方便开发调试,关键代码如下:

@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
  _startTime = DateTime.now();
  Log.d('----------Start----------');
  if (options.queryParameters.isEmpty) {
    Log.d('RequestUrl: ${options.baseUrl}${options.path}');
  } else {
    Log.d('RequestUrl: ${options.baseUrl}${options.path}?${Transformer.urlEncodeMap(options.queryParameters)}');
  }
  // 打印请求方法、头信息等...
  super.onRequest(options, handler);
}

@override
void onResponse(Response<dynamic> response, ResponseInterceptorHandler handler) {
  _endTime = DateTime.now();
  final int duration = _endTime.difference(_startTime).inMilliseconds;
  // 打印响应状态码、数据等...
  Log.d('----------End: $duration 毫秒----------');
  super.onResponse(response, handler);
}

实际应用场景

网络拦截器在整个项目中被广泛应用,例如登录模块lib/login/page/login_page.dart中的登录请求:

void _login() async {
  // 表单验证...
  
  try {
    Loading.show(context);
    var result = await LoginRepository.login(
      username: _nameController.text,
      password: _passwordController.text,
    );
    if (result != null) {
      // 登录成功处理...
      SpUtil.putString(Constant.a***essToken, result.a***essToken ?? '');
      SpUtil.putString(Constant.refreshToken, result.refreshToken ?? '');
      // 跳转主页...
    }
  } catch (e) {
    // 错误处理...
    Toast.show(ExceptionHandle.handleException(e));
  } finally {
    Loading.dismiss(context);
  }
}

总结

Flutter Deer的网络拦截器设计遵循了职责单一原则,通过不同拦截器处理特定功能,实现了代码的解耦和复用。Token自动刷新机制提升了用户体验,统一的错误处理和日志系统则方便了开发和问题定位。

项目相关资源:

  • 拦截器实现:lib/***/intercept.dart
  • 网络工具类:lib/***/dio_utils.dart
  • 错误处理:lib/***/error_handle.dart
  • 官方文档:docs/CHANGELOG.md

通过这种分层设计,Flutter Deer构建了健壮的网络请求系统,为应用的稳定运行提供了有力保障。开发者可以参考这种实现方式,构建自己项目的网络层架构。

【免费下载链接】flutter_deer 🦌 Flutter 练习项目(包括集成测试、可访问性测试)。内含完整UI设计图,更贴近真实项目的练习。Flutter practice project (including integration testing and a***essibility testing). Contains ***plete UI design drawings for a more realistic practice project. 项目地址: https://gitcode.***/gh_mirrors/fl/flutter_deer

转载请说明出处内容投诉
CSS教程网 » Flutter Deer网络拦截器设计:Token刷新与错误处理

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买