Syntax for using Lazy<T>
lateinit var expensiveObject: Lazy<ExpensiveObject>
When using Lazy, unless you call get(), the object is never going to be created.
Subsequent calls to any given instance of Lazy<T> will return the same underlying instance of T.
Using Lazy adds the semantic overhead of having to use get().
Lazy locks a Provider with a DoubleCheck making it more costly than not having Lazy. DoubleCheck will try to access the object, if not initiated, it will lock and initialize the object.
Singleton and Lazy are different things, use them accordingly.
Use Lazy if you have an expensive object that may not get used.
Always measure and know the internals of what you plan to use. Using Lazy may save you a few milliseconds during start up time but the cost of using DoubleCheck wrapping a Provider and the overhead of having to use get() doesn’t make it worth it if the object is going to be used for sure.