一、 GetX 整体架构概述
从源码结构看,GetX 并非单一模块,而是由三大核心模块组成,彼此协同支撑整体功能,源码核心目录结构如下:
get/
├── lib/
│ ├── state_manager/ // 状态管理核心(GetBuilder/Obx/GetX)
│ ├── dependency_injection/ // 依赖注入容器(Get.put/Get.find)
│ ├── navigation/ // 路由管理(非本次重点,暂不展开)
│ └── core/ // 基础工具类(生命周期、全局配置等)
核心依赖关系:依赖注入模块 为 状态管理模块 提供控制器生命周期管理,响应式模块 为 状态管理模块 提供自动刷新能力,三者共同构成 GetX 的核心骨架。
二、 依赖注入(DI)模块:GetX 状态管理的基石
GetX 的依赖注入是其区别于 Provider/Bloc 的核心特性之一,源码核心实现位于 dependency_injection/get_instance.dart 文件中,核心是全局单例容器 + 生命周期绑定。
1. 核心容器:GetInstance 类(全局单例)
GetInstance 是 GetX 依赖注入的核心载体,本质是一个键值对缓存容器,用于存储所有注册的控制器(或其他实例),源码核心实现简化如下:
class GetInstance {
// 全局单例(Dart 私有构造函数实现单例模式)
static final GetInstance _instance = GetInstance._internal();
factory GetInstance() => _instance;
GetInstance._internal();
// 核心缓存容器:存储实例的键值对,key 为 类型+tag,value 为实例对象及元数据
final Map<String, _InstanceBuilderFactory> _singl = {};
// 存储实例的生命周期信息:是否永久存活、绑定的路由等
final Map<String, _InstanceInfo> _instanceInfo = {};
}
- 核心设计:通过
_singl字典缓存实例,键的格式为“${T.toString()}:$tag”(默认 tag 为空字符串),确保不同类型/不同 tag 的实例不冲突。 - 单例模式:通过私有构造函数
_internal()和工厂构造函数factory GetInstance()实现全局唯一的GetInstance实例,所有Get.put/Get.find操作都基于该单例。
2. Get.put():实例注册核心实现
Get.put() 是将实例存入依赖容器的入口方法,源码核心逻辑位于 GetInstance.put(),简化如下:
Future<T> put<T>(
T dependency, {
String? tag,
bool permanent = false, // 是否永久存活(默认false:路由销毁时自动销毁)
@Deprecated('Use `permanent` instead') bool lazy = true,
}) async {
// 1. 生成唯一 key(类型 + tag)
final key = _getKey<T>(tag);
// 2. 若实例已存在,直接返回现有实例
if (_singl.containsKey(key)) {
return _singl[key]!.getInstance() as T;
}
// 3. 创建实例构建器,缓存实例到 _singl 容器
_singl[key] = _InstanceBuilderFactory(
builder: () => dependency,
isSingleton: true,
);
// 4. 记录实例生命周期信息(是否永久存活、注册时间等)
_instanceInfo[key] = _InstanceInfo(
permanent: permanent,
type: T,
tag: tag,
);
// 5. 返回已缓存的实例
return dependency;
}
// 生成唯一 key 的辅助方法
String _getKey<T>(String? tag) {
return tag == null ? T.toString() : '${T.toString()}:$tag';
}
- 关键逻辑:
- 生成唯一键:避免同类型不同实例的冲突(如
Get.put(CountController(), tag: "first")和Get.put(CountController(), tag: "second")是两个独立实例)。 - 缓存去重:若容器中已存在对应 key 的实例,直接返回,确保单例特性(默认情况下)。
- 生命周期标记:通过
permanent参数标记实例是否永久存活,为后续自动销毁提供依据。
- 生成唯一键:避免同类型不同实例的冲突(如
3. Get.find():实例获取核心实现
Get.find() 是从依赖容器中获取实例的入口方法,源码核心逻辑位于 GetInstance.find(),简化如下:
T find<T>({String? tag}) {
// 1. 生成唯一 key
final key = _getKey<T>(tag);
// 2. 若 key 不存在,抛出异常(未注册的实例无法获取)
if (!_singl.containsKey(key)) {
throw "Instance of $T not found. You must call Get.put($T()) first.";
}
// 3. 从容器中获取实例并返回
final instance = _singl[key]!.getInstance() as T;
return instance;
}
- 关键特性:无需
BuildContext,直接通过类型 + tag 从全局容器中获取实例,这是 GetX 对比 Provider 的核心优势(Provider 依赖InheritedWidget上下文获取实例)。
4. 控制器自动销毁:生命周期绑定实现
GetX 控制器(继承 GetxController)的自动销毁功能,源码核心依赖 GetxController 的生命周期方法 + GetInstance 的缓存清理逻辑,步骤如下:
- 控制器生命周期定义:
GetxController源码中定义了核心生命周期方法,简化如下:
abstract class GetxController extends DisposableInterface {
// 初始化时调用
@mustCallSuper
void onInit() {}
// 初始化完成后调用
@mustCallSuper
void onReady() {}
// 销毁时调用(核心:释放资源、取消订阅)
@mustCallSuper
void onClose() {}
}
- 路由生命周期绑定:当使用 GetX 路由时,路由销毁时会触发
GetInstance的delete()方法,清理非permanent标记的实例,简化如下:
void delete<T>({String? tag, bool force = false}) {
final key = _getKey<T>(tag);
final info = _instanceInfo[key];
// 仅清理 非永久存活 或 强制清理 的实例
if (info == null || (info.permanent && !force)) {
return;
}
// 1. 调用控制器的 onClose() 方法,释放资源
final instance = _singl[key]?.getInstance();
if (instance is GetxController) {
instance.onClose();
}
// 2. 从缓存容器中移除实例
_singl.remove(key);
_instanceInfo.remove(key);
}
- 核心优势:无需手动管理控制器销毁,避免内存泄漏,这是 GetX 对比手动创建控制器的核心优化。
三、 非响应式状态管理:GetBuilder 源码实现
GetBuilder 是 GetX 非响应式状态管理的核心,源码位于 state_manager/get_builder.dart,核心原理是手动标记状态变更 + 观察者订阅通知。
1. 核心类结构
GetBuilder 依赖两个核心类协同工作:
GetxController:维护状态变量,提供update()方法标记状态变更。GetBuilder<T>:作为观察者,订阅控制器的状态变更,触发 UI 重建。
2. update() 方法:状态变更标记实现
update() 方法是触发 GetBuilder 刷新的关键,源码位于 GetxController 中(继承自 DisposableInterface),简化如下:
abstract class GetxController extends DisposableInterface {
// 存储该控制器对应的观察者(GetBuilder)列表
final List<Function()> _updaters = [];
// 手动触发状态更新
void update([List<Object>? ids, bool condition = true]) {
if (!condition) return;
// 遍历所有观察者,通知其刷新 UI
for (final updater in _updaters) {
updater();
}
}
// 注册观察者(由 GetBuilder 调用)
void addListener(Function() listener) {
_updaters.add(listener);
}
// 移除观察者(GetBuilder 销毁时调用)
void removeListener(Function() listener) {
_updaters.remove(listener);
}
}
- 核心逻辑:
- 维护观察者列表:
_updaters存储所有订阅该控制器的 GetBuilder 刷新回调。 - 遍历通知:调用
update()时,遍历_updaters列表,执行每个观察者的刷新回调,触发 GetBuilder 重建。 - 可选参数:
ids用于局部刷新(指定仅某个/某些 GetBuilder 刷新),condition用于条件性刷新。
- 维护观察者列表:
3. GetBuilder<T>:观察者订阅与 UI 重建实现
GetBuilder<T> 是一个 StatefulWidget,其状态类 _GetBuilderState<T> 负责订阅控制器的状态变更,源码简化如下:
class GetBuilder<T extends GetxController> extends StatefulWidget {
final Widget Function(T) builder;
final T? init;
final String? tag;
final bool global; // 是否使用全局控制器(默认true)
const GetBuilder({
required this.builder,
this.init,
this.tag,
this.global = true,
Key? key,
}) : super(key: key);
@override
_GetBuilderState<T> createState() => _GetBuilderState<T>();
}
class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
late T _controller;
@override
void initState() {
super.initState();
// 1. 获取控制器实例(全局容器 或 局部初始化)
_controller = widget.global
? Get.find<T>(tag: widget.tag)
: (widget.init ?? Get.put(widget.init!, tag: widget.tag));
// 2. 注册刷新回调:将 setState 作为观察者添加到控制器的 _updaters 列表
_controller.addListener(_update);
}
// 刷新回调:触发 State 重建,更新 UI
void _update() {
if (mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
// 3. 构建 UI:传递控制器给 builder 方法
return widget.builder(_controller);
}
@override
void dispose() {
// 4. 移除观察者:避免内存泄漏
_controller.removeListener(_update);
super.dispose();
}
}
- 核心流程:
- 控制器获取:优先从全局依赖容器中获取(
global: true),否则使用局部初始化的控制器。 - 订阅状态:将
_update方法(内部调用setState)注册到控制器的_updaters列表,完成观察者订阅。 - 触发重建:当控制器调用
update()时,_update方法被执行,通过setState触发 GetBuilder 局部重建。 - 取消订阅:GetBuilder 销毁时,从控制器的
_updaters列表中移除_update方法,避免内存泄漏。
- 控制器获取:优先从全局依赖容器中获取(
4. 局部刷新:ids 参数实现原理
GetBuilder 支持通过 ids 参数实现精准局部刷新,源码核心在 update() 方法和 GetBuilder 的初始化逻辑中,简化如下:
// 1. GetxController 的 update 方法增强
void update([List<Object>? ids, bool condition = true]) {
if (!condition) return;
// 若未传入 ids,通知所有观察者
if (ids == null) {
for (final updater in _updaters) {
updater();
}
return;
}
// 若传入 ids,仅通知匹配 id 的观察者
for (final updater in _updaters) {
if (ids.contains(updater.id)) { // 简化:实际源码中 updater 携带 id 信息
updater();
}
}
}
// 2. GetBuilder 传入 id 参数
GetBuilder<CountController>(
id: 'count1', // 唯一标识
builder: (controller) => Text("计数:${controller.count}"),
)
// 3. 控制器中指定 id 刷新
void increment() {
count++;
update(['count1']); // 仅刷新 id 为 count1 的 GetBuilder
}
- 核心优势:避免不必要的 UI 重建,提升性能,尤其在多 GetBuilder 绑定同一个控制器的场景下。
四、 响应式状态管理:Obx / .obs 源码实现
GetX 响应式状态管理(Obx/.obs)是其核心亮点,源码位于 state_manager/reactive 目录,核心原理是Dart 扩展方法 + 观察者模式(发布-订阅),无需依赖 Stream。
1. .obs 扩展方法:可观察对象(Observable)创建
.obs 是 GetX 为所有类型提供的扩展方法,用于将普通对象转化为可观察对象(Observable),源码核心位于 reactive/extensions.dart,简化如下:
// 为所有类型 T 提供 .obs 扩展方法
extension ReactiveExtension<T> on T {
Rx<T> get obs => Rx<T>(this);
}
// 核心可观察对象类:Rx<T>
class Rx<T> extends RxNotifier<T> {
Rx(T initialValue) : super(initialValue);
// 重写 value 属性,实现状态变更监听
@override
set value(T newValue) {
if (_value == newValue) return; // 避免重复更新
super.value = newValue;
// 状态变更时,通知所有订阅者
notifyListeners();
}
@override
T get value => super.value;
// 简化赋值语法(可选)
T call([T? v]) {
if (v != null) {
value = v;
}
return value;
}
}
// 可观察对象基类:RxNotifier(维护订阅者列表)
class RxNotifier<T> extends ListNotifier {
T _value;
RxNotifier(this._value);
// 订阅者列表(存储 Obx 的刷新回调)
final List<Function()> _listeners = [];
// 添加订阅者
void addListener(Function() listener) {
_listeners.add(listener);
}
// 移除订阅者
void removeListener(Function() listener) {
_listeners.remove(listener);
}
// 通知所有订阅者
void notifyListeners() {
for (final listener in _listeners) {
listener();
}
}
}
- 核心逻辑:
- 扩展方法:
ReactiveExtension为所有类型提供.obs方法,快速创建Rx<T>实例。 - 状态拦截:重写
value属性的set方法,当值发生变更时,自动调用notifyListeners()通知所有订阅者。 - 避免重复更新:通过
_value == newValue判断,避免相同值重复触发刷新,提升性能。
- 扩展方法:
2. Obx 组件:观察者订阅与 UI 重建
Obx 是监听可观察对象(Rx<T>)状态变更的核心组件,源码位于 reactive/obx.dart,本质是一个 StatelessWidget(内部通过 Observer 实现订阅),简化如下:
class Obx extends StatelessWidget {
final Widget Function() builder;
const Obx(this.builder, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// 核心:通过 Observer 组件实现订阅
return Observer(
builder: (_) => builder(),
name: 'Obx',
);
}
}
// 核心观察者类:Observer
class Observer extends StatefulWidget {
final Widget Function(BuildContext) builder;
final String? name;
const Observer({
required this.builder,
this.name,
Key? key,
}) : super(key: key);
@override
_ObserverState createState() => _ObserverState();
}
class _ObserverState extends State<Observer> {
// 刷新回调:触发 UI 重建
void _update() {
if (mounted) {
setState(() {});
}
}
@override
void initState() {
super.initState();
// 注册全局订阅者:GetX 会在可观察对象被访问时,自动绑定该观察者
Get.reactiveManager.addListener(_update);
}
@override
Widget build(BuildContext context) {
// 1. 标记当前观察者为活跃状态
Get.reactiveManager.startTracking();
// 2. 构建 UI:执行 builder 方法,访问可观察对象
final widget = this.widget.builder(context);
// 3. 停止跟踪,绑定可观察对象与当前观察者
Get.reactiveManager.stopTracking();
return widget;
}
@override
void dispose() {
// 4. 移除订阅者,避免内存泄漏
Get.reactiveManager.removeListener(_update);
super.dispose();
}
}
3. 自动绑定核心:ReactiveManager 跟踪机制
Obx 能自动感知 .obs 对象的访问,核心依赖 ReactiveManager 类的跟踪机制,源码位于 reactive/reactive_manager.dart,简化如下:
class ReactiveManager {
// 全局单例
static final ReactiveManager _instance = ReactiveManager._internal();
factory ReactiveManager() => _instance;
ReactiveManager._internal();
// 当前活跃的观察者刷新回调
Function()? _currentListener;
// 开始跟踪:记录当前观察者的刷新回调
void startTracking() {
// _currentListener 由 Observer 传入(即 _update 方法)
}
// 停止跟踪:解除当前观察者的绑定
void stopTracking() {
_currentListener = null;
}
// 当可观察对象被访问时,自动绑定观察者
void track<T>(RxNotifier<T> rx) {
if (_currentListener != null && !rx._listeners.contains(_currentListener)) {
// 将当前观察者的刷新回调添加到可观察对象的订阅者列表
rx.addListener(_currentListener!);
}
}
}
- 核心流程(自动绑定):
Observer构建时,调用startTracking(),将自身的_update方法设为_currentListener(当前活跃观察者)。- 执行
builder方法,当访问Rx<T>对象的value属性时,会触发ReactiveManager的track()方法。 track()方法将_currentListener(_update)添加到Rx<T>的订阅者列表_listeners中,完成自动绑定。Observer构建完成后,调用stopTracking(),解除当前活跃观察者标记。- 当
Rx<T>的value变更时,调用notifyListeners(),执行_update方法,触发setState重建ObxUI。
4. 关键特性:精准局部重建
Obx 仅会刷新自身包裹的 UI 组件,核心原因是:
- 每个
Obx对应一个独立的Observer状态类,其_update方法仅触发自身的setState。 - 可观察对象仅通知订阅它的
Observer,不会影响其他未订阅的组件,实现精准局部刷新,性能优于全局重建。
五、 GetX 源码核心设计总结
- 依赖注入核心:基于
GetInstance全局单例容器,通过Get.put()缓存实例、Get.find()获取实例,配合permanent参数实现控制器自动销毁,无需手动管理生命周期。 - 非响应式状态管理(GetBuilder):基于
GetxController的_updaters观察者列表,update()手动通知刷新,GetBuilder订阅并通过setState实现局部重建,性能开销极低。 - 响应式状态管理(Obx/.obs):
.obs通过扩展方法将普通对象转为Rx<T>可观察对象,重写value属性拦截状态变更。Obx基于Observer组件,通过ReactiveManager自动跟踪可观察对象的访问,完成订阅绑定。- 状态变更时,
Rx<T>通知所有订阅者,Observer触发局部重建,无需手动调用update()。
- 核心优势底层支撑:
- 无需
BuildContext:依赖全局GetInstance容器,而非InheritedWidget。 - 精准局部刷新:观察者模式确保仅订阅的组件重建,避免无效开销。
- 低侵入性:无需顶层包裹组件,按需使用
GetBuilder/Obx,代码简洁。
- 无需