What is GetX Smart Management?
One of GetX's most powerful features is its smart management system, which automatically handles the lifecycle of your controllers and dependencies. It tracks when a controller is being used and disposes of it when it's no longer needed, preventing memory leaks. This guide explains how this system works and how to control it with permanent, fenix, and proper registration patterns.
How Smart Management Works
GetX monitors whether a controller is actively being used. A controller is considered "in use" when:
- It is injected via
Get.putand the widget that calledGet.putis still in the widget tree. - It is accessed via
Get.findinside a widget that is currently mounted. - It is part of a route that is currently active.
When a controller is no longer referenced by any active widget or route, GetX automatically calls its onClose() method and disposes it. This is the default behavior and helps keep your app memory‑efficient.
Controller Lifecycle in Routes
When you use bindings with GetPage, GetX ties the controller lifecycle to the route. When the route is popped, the controller is automatically disposed (unless marked permanent).
If you register a controller inside a widget using Get.put (not recommended outside of simple cases), the controller will be disposed when that widget is removed from the tree.
Controlling Lifecycle with permanent
Sometimes you want a controller to live for the entire app duration. Use permanent: true to prevent automatic disposal.
fenix – Resurrection After Disposal
If you want a controller to be recreated after it has been disposed (e.g., when the user revisits a route), use fenix: true with lazyPut. When the route is popped, the controller is disposed, but the next Get.find will create a fresh instance.
Smart Management in Practice
- Default (no flags) – The controller is disposed when the route is popped or when the widget that created it is removed.
permanent: true– The controller lives forever. Use for app‑wide services.fenix: true– The controller is disposed when not used, but can be recreated automatically later.Get.create– Always returns a new instance; does not cache.
Detecting Disposal
Override onClose() to perform cleanup and confirm that disposal is happening as expected.
Common Pitfalls
- Registering controllers inside
build– Creates a new controller on every rebuild, causing leaks and duplicate instances. ✅ Register ininitState, bindings, oronInitof other controllers. - Assuming a controller is still alive – Always check
Get.isRegistered<T>()before usingGet.findif you're not certain. - Forgetting to set
permanentfor global services – They might be disposed unexpectedly when a route is popped. ✅ Usepermanent: truefor app‑wide services. - Not disposing resources in
onClose– Even though the controller is disposed, streams and timers may still be active. ✅ Always clean up inonClose.
Best Practices
- Use bindings – Let GetX manage the controller lifecycle automatically based on routes.
- Avoid
Get.putinside widgets – Prefer bindings or at least useGet.lazyPutif you must create a controller in a widget. - Use
permanentonly for truly global dependencies – Like authentication, theme, database services. - Use
fenixfor controllers that should be recreated when needed – Especially for routes that may be opened multiple times. - Test disposal – Use
onCloselogs during development to verify controllers are being disposed correctly.
FAQ
- Q: How does GetX know when a controller is no longer used?
A: GetX uses an internal reference counter. Each timeGet.findis called from a widget that is mounted, it increments a count. When the widget is unmounted, it decrements. When the count reaches zero, the controller is disposed. - Q: What happens if I use
Get.putin multiple places?
A: The first call creates the instance; subsequent calls return the same instance (unless tags are used). The reference count is increased accordingly. - Q: Can I manually delete a controller?
A: Yes, callGet.delete<MyController>(). It will callonCloseand remove it from the registry. - Q: Why is my controller not being disposed?
A: It might be markedpermanent, or there may still be a reference to it in a widget that is still mounted. Check if you are usingGet.putinside a widget that never gets removed. - Q: How to dispose a controller when using
Get.lazyPutwithoutfenix?
A: It will be disposed when the route is popped or when the last reference is removed. To force disposal, useGet.delete.
Conclusion
GetX smart management eliminates the need to manually dispose controllers, reducing memory leaks and boilerplate. By understanding how it works and using permanent and fenix appropriately, you can build efficient, scalable Flutter apps.