【Flutter】基于 GetX 实现 Dio 的生命周期自动化

前言

在前文【传送门】的网络请求封装中我们基于DIO的网络请求进行了封装,本身是没什么问题的,但是细想之下,我们并没有处理取消网络的逻辑。

在之前客户端的开发中,例如 Android 的 ViewModel 中我们不管是通过协程的绑定生命周期自动取消,还是使用 RxJava/RxKotlin 的方式手动收集 Disposable 并且在销毁的时候释放,我们都是需要做处理的。

而在 Flutter 中由于我们是基于 Get 框架实现的,那么在 GetxController 中我们并没有处理网络请求的取消,这样就可能会发生内存泄露、占用带宽和系统资源、空指针等。

所以我们需要考虑如何在 GetxController 中实现自动化的 DIO 的 CancelTag 管理。

实现的方式有很多,这里列举三种方式:一种是我们常用的基类封装,另一种是使用扩展方法实现,还有一种是混入实现,下面就分别看看如何实现吧。

一、基类的实现

其实我个人不推荐这种方法,不太优雅,因为可能我们自己封装了一个 BaseController 除了你自己其他人接触到你的项目就是一脸懵,直接改变了原本类,容易让人摸不着头脑。

scala 复制代码
import 'package:dio/dio.dart';
import 'package:get/get.dart';

class BaseController extends GetxController {
  // Dio 实例可以从外部传入,也可以在BaseController中创建
  final Dio dio;
  // 创建一个 CancelToken 用于取消Dio请求
  final CancelToken cancelToken = CancelToken();
  
  BaseController({required this.dio});

  @override
  void onClose() {
    // 当控制器关闭时,取消所有的 Dio 请求
    cancelToken.cancel("Controller has been disposed");
    super.onClose();
  }
  
  // 其他公共方法或属性 ...
}

使用的时候:

scala 复制代码
class MyController extends BaseController {
  MyController({required Dio dio}) : super(dio: dio);

  void fetchData() async {
    try {
      final response = await dio.get(
        'https://example.com/data',
        cancelToken: cancelToken,
      );
      // 处理响应 ...
    } catch (e) {
      if (CancelToken.isCancel(e)) {
        print("请求取消:$e");
      } else {
        // 处理其他错误 ...
      }
    }
  }
  
  // 其他方法 ...
}

此时就是所有的 Controller 都需要继承你自定义的 BaseController,以后有什么逻辑就往 Base 里面加,反正能实现我的需求了。

二、扩展实现

使用扩展可能实现类似的功能,并且没有改变本身的 Controller 是继承与 GetxController 这个对象,让同事或者其他开发者一目了然。

但是缺点是扩展的逻辑不明显,如果你不告诉其他开发者,它甚至都不知道你在里面添加了什么逻辑,如果是 CancelToken 这种无感逻辑还好,如果是一些特定的逻辑或者有一些Bug坑,那真是找都不好找。

java 复制代码
import 'package:dio/dio.dart';
import 'package:get/get.dart';

extension CancelableGetController on GetxController {
  // 关联 CancelToken
  CancelToken _cancelToken = CancelToken();

  // 获取CancelToken的方法
  CancelToken get cancelToken => _cancelToken;

  // 取消请求的方法
  void cancelRequests() {
    _cancelToken.cancel("请求被取消");
  }

  // 为了确保自动取消网络请求,在类销毁时调用cancelRequests
  @override
  void onClose() {
    cancelRequests();
    super.onClose();
  }
}

我们使用扩展就无需使用 BaseController 了:

scala 复制代码
class MyController extends GetxController {
  final Dio dio = Dio();

  void fetchSomething() async {
    try {
      final response = await dio.get(
        'https://myapi.com/data',
        cancelToken: cancelToken, // 使用扩展提供的CancelToken
      );
      // 处理响应
    } catch (e) {
      // 错误处理
    }
  }
}

可以说是使用简单,逻辑无感,适用与一些特定场景。

三、混入实现

使用 mixin 的方式呢,和扩展比较类似,只是可以选装了,比如我这个 SettingController 它没有网络请求,只有一些本地数据处理逻辑,那么我就可以选择不混入 DIO 的 CancelToken 逻辑,如果我是 UserProfileController 这肯定是有网络请求我就可以选择混入DIO 的 CancelToken 逻辑。

可选装是他最大的有点,其他开发者可能一目了然,哦,你这个 Controller 加了一些奇怪的逻辑,他就能点进去看看你的混入逻辑,比较方便调试。

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

mixin CancelableMixin on GetxController {
  CancelToken _cancelToken = CancelToken();

  CancelToken get cancelToken => _cancelToken;

  @override
  void onClose() {
    _cancelToken.cancel("请求被取消");
    super.onClose();
  }
}

使用的时候:

scala 复制代码
class MyController extends GetxController with CancelableMixin {
  final Dio dio = Dio();

  void fetchSomething() async {
    try {
      final response = await dio.get(
        'https://myapi.com/data',
        cancelToken: cancelToken,
      );
      // 处理响应
    } catch (e) {
      // 错误处理
    }
  }
}

总结

三种方式都可以实现类似的效果,如果你就像使用基类完全没问题,如果你想隐藏你的业务逻辑使用扩展的方法很难被人发现,如果你想做成可配置的效果,更加极限的内存优化,那么使用混入的方式比较适合你。

什么?我用的哪一种?我用的混入方式,不过我在魔改 GetxController 其他方式也用到了扩展方法,对于一些必须存在的自定义且无感的逻辑我还是喜欢用扩展的方式,如果是可用可不用这种配置选项我更喜欢用混入的方式。

那么本期内容就到这里,如讲的不到位或错漏的地方,希望同学们可以评论区指出。

本文的代码已经全部贴出,部分没贴出的代码可以在前文中找到,我的 Flutter Demo 项目正在整理中,后期开源了会更新文章链接。

如果感觉本文对你有一点点的启发,还望你能点赞支持一下,你的支持是我最大的动力啦!

Ok,这一期就此完结。

相关推荐
一只大侠的侠2 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
renke33645 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端