GetX依赖注入异常:未在Obx中用变量致实例状态丢失
GetX依赖注入实例丢失/重复创建问题分析与解决
问题本质
你遇到的是GetX依赖注入中实例被意外销毁、重复创建的问题,核心和lazyPut的自动销毁机制、以及GetX对未被监听的Rx变量的回收策略直接相关。
原因拆解
lazyPut的销毁逻辑lazyPut默认会在无有效引用时自动销毁实例。这里的“有效引用”不仅指GetView的关联,更关键的是实例内的Rx变量是否被Obx/GetBuilder等组件监听。如果你的CountPageService里的count变量没有被任何UI组件绑定监听,GetX会判定该实例“无使用价值”,页面跳转时就会销毁它。下次调用Get.find()时会重新创建新实例,导致哈希码不同、状态丢失。- 即便加了
fenix: true,如果实例没有被监听,在页面栈弹出后也可能被GC回收——fenix只是让实例销毁后下次调用Get.find()时自动重建,但之前的状态会完全丢失。
Get.put()未解决的可能原因- 如果你在多个位置重复调用了
Get.put()(比如每个页面的onInit里都执行一次),会强制创建新实例覆盖旧的; - 如果你的
CountPageService是在某个页面的Binding中注入的,页面销毁时该Binding的依赖会被自动清理(除非指定permanent: true); - 可能手动调用过
Get.delete<CountPageService>(),导致实例被销毁后重新创建。
- 如果你在多个位置重复调用了
解决方案
1. 全局永久单例注入(推荐)
对于需要跨页面保持状态的服务,直接在main()中用Get.put()并指定permanent: true,强制实例不被自动销毁:
void main() { // 全局永久单例,生命周期和App一致 Get.put<CountPageService>(CountPageService(), permanent: true); runApp(MyApp()); }
2. 修正lazyPut的使用方式
如果坚持用lazyPut,需满足两个条件:
- 全局注入(在
main()中,而非页面Binding),并开启fenix: true; - 提前初始化实例,避免后续重复创建:
void main() { Get.lazyPut<CountPageService>(() => CountPageService(), fenix: true); // 提前获取实例,确保容器中保留引用 Get.find<CountPageService>(); runApp(MyApp()); }
3. 避免重复注入
检查整个项目的代码,确保CountPageService的注入代码只存在一处,不要在多个Binding或页面中重复执行put/lazyPut。
4. 手动保留引用(应急方案)
如果确实不需要监听Rx变量,可以在App启动后用一个全局变量持有实例,避免被GC回收:
CountPageService? globalCountService; void main() { globalCountService = Get.put<CountPageService>(CountPageService()); runApp(MyApp()); }
GetX内部原理补充
GetX的依赖注入容器通过引用计数+监听状态管理实例生命周期:
- 当实例被
GetView关联,或其内部Rx变量被Obx监听时,容器会增加引用计数,标记实例为“活跃”; - 当引用计数归0(无关联View、无监听的Rx变量),且未设置
permanent: true时,实例会被标记为可销毁,在页面切换或GC时被清理; fenix: true只是让实例销毁后,下次Get.find()会自动重建,但无法保留之前的状态。
内容的提问来源于stack exchange,提问作者Shallow_Wind
相关产品推荐
相关产品推荐

