[Get 源码] GetPageRoute 与 GetxController 的自动回收机制

一、关键源码入口

1. ‌路由生命周期管理 Mixin

typescript 复制代码
dartCopy Code
mixin PageRouteReportMixin<T> on Route<T> {
  @override
  void install() {
    super.install();
    RouterReportManager.reportCurrentRoute(this);
  }

  @override
  void dispose() {
    super.dispose();
    RouterReportManager.reportRouteDispose(this);
  }
}

2. ‌GetPageRoute 核心实现

scala 复制代码
dartCopy Code
class GetPageRoute<T> extends PageRoute<T>
    with GetPageRouteTransitionMixin<T>, PageRouteReportMixin {
  @override
  void dispose() {
    super.dispose();
    final middlewareRunner = MiddlewareRunner(middlewares);
    middlewareRunner.runOnPageDispose();
  }
}

二、引言:Bindings 的魔法

GetX 通过 ‌**Bindings**‌ 机制实现依赖注入与自动回收,其核心逻辑如下:

1. ‌单例注入原理

  • ‌**Bindings 声明**‌:每个路由页面关联一个 Binding 类
  • 注册依赖 ‌:在 dependencies() 方法中调用 Get.lazyPutGet.put
  • 作用域隔离‌:依赖项默认绑定到当前路由生命周期
scala 复制代码
dartCopy Code
class DetailBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => DetailController()); // 路由级单例
  }
}

2. ‌自动回收机制

  • 路由销毁触发 ‌:当 GetPageRoute 被销毁时(页面关闭),触发 RouterReportManager.reportRouteDispose
  • 清理策略 ‌:通过 _removeDependencyByRoute 移除路由关联的控制器
  • 执行顺序 ‌:
    GetPageRoute.dispose()PageRouteReportMixinRouterReportManager → ‌清理依赖

三、重点记录:不同依赖注册方式的差异

1. ‌三种依赖注册方式对比

方法 自动销毁支持 典型场景
Get.put() ❌ 不支持 全局单例(如用户信息管理)
Get.create() ✅ 支持 需要动态参数的控制器
Bindings 绑定 ✅ 支持 路由级作用域控制器(推荐方式)

2. ‌关键差异解析

  • ‌**Get.put() 问题‌:直接通过该方法注册的实例会 ‌ 常驻内存**‌,需手动调用 Get.delete()
  • ‌**Get.create() 优势**‌:与路由绑定,页面关闭时自动触发 onClose()
  • 最佳实践 ‌:始终通过 Bindings 管理控制器,避免内存泄漏

四、MiddlewareRunner 的三大应用场景

1. ‌路由拦截(redirect)

scala 复制代码
dartCopy Code
class AuthMiddleware extends GetMiddleware {
  @override
  RouteSettings? redirect(String? route) {
    if (!isLogin && route == "/profile") {
      return RouteSettings(name: "/login");
    }
    return null;
  }
}

场景‌:未登录用户访问个人主页时跳转登录页

2. ‌参数修改(onPageCalled)

scala 复制代码
dartCopy Code
class ParamsMiddleware extends GetMiddleware {
  @override
  GetPage? onPageCalled(GetPage? page) {
    if (page?.name == "/search") {
      return page?.copy(parameters: {"timestamp": DateTime.now().toString()});
    }
    return page;
  }
}

场景‌:动态添加时间戳参数到搜索页面

3. ‌资源释放(onPageDispose)

scala 复制代码
dartCopy Code
class AnalyticsMiddleware extends GetMiddleware {
  @override
  void onPageDispose() {
    Analytics.reportClose(Get.currentRoute);
  }
}

场景‌:页面关闭时上报用户行为埋点


五、_removeDependencyByRoute 深度解析

1. ‌函数作用

清理与特定路由关联的依赖项,确保内存回收

2. ‌执行流程

scss 复制代码
dartCopy Code
static void _removeDependencyByRoute(Route route) {
  // 清理通过 Get.create() 注册的实例
  if (_routesByCreate.containsKey(route)) {
    _routesByCreate[route]!.forEach((onClose) => onClose());
    _routesByCreate.remove(route);
  }

  // 清理通过 Bindings 注册的依赖
  final keys = _routesKey[route];
  keys?.forEach((key) => GetInstance().delete(key: key));
  _routesKey.remove(route);
}

3. ‌关键设计

  • 双重清理机制‌:

    • ‌**Get.create() 实例**‌:直接执行注册时的 onClose 回调
    • ‌**Bindings 依赖**‌:通过 GetInstance().delete() 触发 onClose()
  • 路由级作用域 ‌:确保不同路由的依赖项 ‌完全隔离


六、总结:GetX 自动回收机制的设计哲学

  1. 生命周期绑定 ‌:
    GetPageRoute 通过重写 dispose() 方法,将控制器生命周期与路由销毁事件强绑定

  2. 中间件扩展性 ‌:
    MiddlewareRunner 提供可插拔的扩展点(参数修改、拦截、埋点)

  3. 依赖治理策略‌:

    • 全局单例由开发者手动管理
    • 路由级依赖由框架自动回收

这种设计在保持灵活性的同时,最大程度避免了 Flutter 应用常见的内存泄漏问题,其实现方式与 Android 的 ViewModel + LiveData 生命周期管理有着异曲同工之妙。

相关推荐
louisgeek1 小时前
Flutter 简介
flutter
JarvanMo12 小时前
关于Flutter架构的小小探讨
前端·flutter
顾林海13 小时前
Flutter 图标和按钮组件
android·开发语言·前端·flutter·面试
yzwdzkn14 小时前
解决Flutter 2.10.5在升级Xcode 16后的各种报错
flutter·macos·xcode
亚洲小炫风16 小时前
flutter json解析增强
flutter·json·json兼容格式
SY.ZHOU17 小时前
Flutter 与原生通信
android·flutter·ios
恋猫de小郭20 小时前
IntelliJ IDEA 2025.1 发布 ,默认 K2 模式 | Android Studio 也将跟进
android·前端·flutter
梦想不只是梦与想20 小时前
鸿蒙系统开发状态更新字段区别对比
android·java·flutter·web·鸿蒙
RichardLai8820 小时前
[Flutter学习之Dart基础] - 集合(List, Set,Map)
android·flutter