What is Get.lazyPut?
Get.lazyPut is a method in GetX that registers a dependency but defers its creation until it is first accessed. This is in contrast to Get.put, which creates the instance immediately. Lazy injection is ideal for improving startup performance and for dependencies that may not be used in every session of your app.
Basic Syntax
How It Works
When you call Get.lazyPut, GetX stores a factory function that creates the instance. The actual object is not instantiated until you (or GetX internally) call Get.find for that type. After that, the instance is cached and reused for subsequent Get.find calls.
When to Use Get.lazyPut
- Improve startup time – Avoid creating many controllers at once when the app launches.
- Optional dependencies – Controllers that are only needed under certain conditions (e.g., admin features).
- Routes with bindings – In
GetPagebindings, usinglazyPutensures controllers are created only when the route is visited. - Large services – Heavy initialisation (e.g., database connections) should be lazy to avoid blocking the UI.
Parameters
The fenix (phoenix) flag, when set to true, allows the instance to be recreated after it has been disposed. This is useful for dependencies that you want to be able to resurrect without re-registering manually.
Setting permanent: true prevents the instance from ever being disposed automatically. This is similar to using Get.put with permanent: true, but the instance is still created lazily.
Use tags to register multiple instances of the same type. Each tag creates a separate lazy registration.
Get.lazyPut vs Get.put
Using with Bindings
The most common pattern is to use Get.lazyPut inside a binding. This ensures that controllers are only created when the route is actually opened.
Best Practices
- Prefer
lazyPutin bindings – Defer creation until the route is visited. - Use
fenix: truefor disposable controllers – Allows recreation after route disposal without re-registration. - Avoid using
lazyPutfor truly global dependencies – UseGet.put(permanent: true)instead if you need the instance immediately. - Don't overuse
permanent– Let GetX dispose controllers automatically when possible. - Check registration before find – Use
Get.isRegisteredto avoid errors when you're not sure if the dependency is registered yet.
Common Mistakes
- ❌ Calling
Get.findbefore any registration – Throws an error. ✅ Always register first, or check withGet.isRegistered. - ❌ Using
lazyPutwhen you need the instance immediately after registration – The instance won't exist yet. ✅ UseGet.putinstead. - ❌ Forgetting to set
fenix: truefor re‑usable controllers – After disposal, they won't be recreated. ✅ Setfenix: trueif you want them to come back to life. - ❌ Assuming
lazyPutcreates a new instance each time – It's still a singleton; useGet.createfor fresh instances.
FAQ
- Q: Can I use
Get.lazyPutwithoutGet.find?
A: Yes, you can register a dependency that may never be used. It will simply never be created. - Q: What happens if I call
Get.lazyPutmultiple times with the same type?
A: Unless you use different tags, the later registration overwrites the earlier one. You can check withGet.isRegisteredfirst. - Q: How do I know if a lazy instance has been created?
A: UseGet.isRegistered<MyController>(). It returnstrueonce the instance has been created (or if it was registered but not yet created? Actually,isRegisteredreturns true as soon as the lazy registration is made, because the dependency is "registered", even if the instance is not yet created. To know if the instance exists, you can check internally, but for most use cases you don't need to distinguish. - Q: Can I convert a lazy registration to a permanent one later?
A: No, once registered, you cannot change its flags. You would need to delete and re‑register. - Q: Is
Get.lazyPutthread‑safe?
A: Yes, GetX is designed for Flutter's single-threaded UI environment.
Conclusion
Get.lazyPut is an essential tool for efficient dependency management in GetX. By deferring creation until the first use, you can significantly improve your app's startup time and reduce memory footprint. Combined with bindings, fenix, and tags, it provides a flexible and powerful way to manage dependencies in large Flutter applications.