1

I found the answer for Kotlin Lazy objects, using isInitialized() here: Kotlin: Check if lazy val has been initialised

But seems like dagger.Lazy doesn't have the same public method.

This is how I lazily inject using Dagger:

@Inject internal lateinit var someService: dagger.Lazy<SomeService>

How to check if someService is already initialized without calling someService.get() which will initialize it? Other than introducing a boolean flag and keep track of it ourselves..

Thanks!

Bruce
  • 2,357
  • 5
  • 29
  • 50

1 Answers1

1

There isn't a way to check; Lazy only has one method, get, making it a functional interface or "Single Abstract Method (SAM)" interface much like JSR330's Provider, Guava's Supplier, and JDK8 Supplier.

This abstraction is important, because in Dagger the definition of Lazy is more complicated and there is more than one implementation. For scoped bindings, the internal InstanceFactory itself implements Lazy, so the built in Provider<Lazy<T>> available for each T in the graph can be implemented using a class ProviderOfLazy that can simply return the internal Provider or InstanceFactory rather than creating a new wrapper instance. With that in mind, the instance of Lazy you interact with might be a shared one, so a hypothetical isInitialized might be ambiguous: Does it mark that the scoped binding was ever accessed, or just the local Lazy injection point you requested? Would that behavior change based on whether you mark the binding scoped or not in a faraway Module file? You could also imagine an implementation where every Lazy injection got its own instance, and each would locally track whether it had ever had its get called regardless of scoping. This is in contrast to Kotlin's Lazy, in which each instance wraps exactly one initializer function and consequently has less ambiguity.

Also, Kotlin's Lazy has multiple synchronization modes from which you can select, some of which have undefined behavior when called concurrently. isInitialized is never synchronized in any of those modes, so in a concurrent environment you might receive false while the value is in mid-construction, or it may even be fully constructed on a different thread and the value is simply not yet visible from the thread calling isInitialized.

If you need to be able to check on a Lazy-like status, you'll need to specify how wide you care about construction and how thread-safe you want the result to be, which is custom enough to warrant your own implementation.

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251