Search code examples
singletoneager-loadingdagger-2

Dagger 2 - how to create/provide a EagerSingleton


I am having trouble with the Dagger 2 dependency injection framework. I would like to create an EagerSingleton. I assume that dagger 2 creates lazy loaded singletons when I use the @Singleton annotation. How do I create EagerSingleton using the Dagger 2 framework ?


Solution

  • I figured out how to do this:

    as per the docs dagger does not support eagerSingletons directly so:

    Work around this by creating an EagerSingletons class that declares static fields for each eager singleton. Method injection.

    So i created a EagerSingletons class in any module i want to use a eager singleton. In that eagerSingletons class i would declare any singleton i want to use. Thats it, dagger then makes the singletons eager.

    UPDATE: The reason i used dagger 1 as an example, is this is how its done in dagger 2. there really is no mechanism for eagerSingletons. you have to make it using a static field. Let me give you an example of how you might create a eagerSingleton:

    In every module you need a eager singleton you could have this:
        //assume this file is called myModule.java
    
    
    
    static EagerObjects eagerObjects;
    
        public static void initEagerObjects() {
            if (eagerObjects == null) {
                eagerObjects = new EagerObjects();
            }
        }
    //so far so good, only one object will be created, lets inject what we need immediately
        public static class EagerObjects {
    
            public EagerObjects() {
              //inject right away,you'll have to figure out a way to pass the graph in. by constructor param should be fine
                getGraph().inject(this);
            }
    
            //make this injection static
            @Inject
            static CoffeePot coffeePot;
        }
    }
    

    Now to find a way to call this right away on application launch....

    Back in your dagger component or in the application class you extend you can have a static method to call each one of these per module:

      static void injectAllEagerObjects() {
                myModule.initEagerObjects();
                someOtherModule.initEagerObjects();
                //...all of them can be here since there static
    

    }

    now we are almost done, just have to call it at application launch. So right after you create your graph from application you have to call injectAllEagerObjects() (and probably pass in your graph instance there if you want). This will initialize the eager singletons right way and only once.

    all this being said, i wish dagger just had a annotation you could use like this: @singleton(eager=true) but static fields, this is what they recommend for now.