Leem.fin
Leem.fin

Reputation: 42592

Dagger 2 doesn't provide my class as singleton, why?

I have a class:

public class MyFactory {
    public MyFactory() {
    }

}

My Dagger module:

@Module
public class MyModule {
    @Provides
    @Singleton
    public MyFactory provideMyFactory() {
        return new MyFactory();
    }
}

My component:

@Singleton
@MyScope
@Component(modules = MyModule.class)
public interface MyComponent {
    MyFactory getMyFactory();
}

My Scope:

@Scope
@Retention(RetentionPolicy.CLASS)
public @interface MyScope {
}

I expect MyFactory instance being provided by Dagger2 is a singleton however, it is not. I tried to call following code in two places of my project:

MyFactory factory = DaggerMyComponent.builder()
                .build()
                .getMyFactory();
Logcat.d("tag", "factory = " + factory);

My log shows me :

factory = :com.my.app.MyFactory@eaa9330
factory = :com.my.app.MyFactory@8bd552e

As you can see, they are two instances. So, My questions are:

Question 1. In above case, why Dagger doesn't provide MyFactory as a singleton??

Question 2. With my above code, does everytime calling DaggerMyComponent.builder().build(); create a new instance of MyComponent?

Question 3. Dagger also allow developer's class instance to be injectable by place a @Inject annotation in constructor without bothering having the module:

public class MyFactory {
    @Inject
    public MyFactory() {
    }
}

developer can use it just by @Inject MyFactory factory; In this case, how to make MyFactory singleton with Dagger 2?

Upvotes: 2

Views: 663

Answers (1)

David Medenjak
David Medenjak

Reputation: 34532

Scopes are per component. If you create multiple components then you create multiple objects. @Singleton is no exception.

// same component
DaggerMyComponent firstComponent = DaggerMyComponent.builder().build();

firstComponent.getMyFactory() == firstComponent.getMyFactory(); // true


// second component
DaggerMyComponent secondComponent = DaggerMyComponent.builder().build();

firstComponent.getMyFactory() == secondComponent.getMyFactory(); // false

You will have to keep the component instances and reuse them, or you will always create new references. E.g. A common way is to place the @Singleton AppComponent within your Application and grab it from there when needed.

In this case, how to make MyFactory singleton with Dagger 2?

With constructor injection you just add the scope to the top of the class.

@Singleton // place scope _on_ the class
public class MyFactory {
  @Inject
  public MyFactory() {
  }
}

Upvotes: 4

Related Questions