Monday, December 4, 2017

Dagger singleton creating new instance every time

Leave a Comment

I have a module as follows.

@Module public class AppModule {     private final Application app;      public AppModule(Application app) {         this.app = app;     }      @Provides     @Architecture.ApplicationContext     Context provideContext() {         return app;     }      @Provides //scope is not necessary for parameters stored within the module     public Context context() {         return provideContext();     }      @Singleton     @Provides     Application provideApp() {         return app;     }      @Singleton     @Provides     SoundsRepository provideSoundsRepository(Context context, SoundsDAO soundsDAO) {         return new SoundsRepository(context, soundsDAO);     } } 

A component like this.

@Singleton @Component(modules = AppModule.class) public interface AppComponent {      void inject(Global global);      void inject(MainActivity mainActivity);       @Architecture.ApplicationContext     Context getContext();      Application getApplication();      void inject(PostView postView);      void inject(MediaPlayerService mediaPlayerService); } 

In activity, fragment or service, I do this

@Inject     SoundsRepository soundsRepository;  @Override protected void onCreate(...) {     //....     ((Global) getApplication()).getComponent().inject(this); } 

In SoundsRepository

@Singleton public class SoundsRepository {     @Inject     public SoundsRepository(Context context, SoundsDAO soundsDAO) {         this.context = context;         this.soundsDAO = soundsDAO;         System.out.println(TAG + "INIT");     }     // ....  } 

So, now, every time I start to access an activity or service where SoundsRepository is injected, I get a new instance, I mean, the constructor of "SoundsRepository" fires again.

What am I doing wrong?

EDIT : Inject in Application Class

public class Global extends MultiDexApplication {      protected AppComponent appComponent;     private boolean calledAlready = false;      @Override     public void onCreate() {         super.onCreate();         //if (LeakCanary.isInAnalyzerProcess(this)) return;         //LeakCanary.install(this);         initFirebasePersistance();         appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();         appComponent.inject(this);         FrescoUtil.init(getApplicationContext());     }       public AppComponent getComponent() {         return appComponent;     } } 

1 Answers

Answers 1

  1. In your module you have a method that provides an instance of SoundsRepository - good
  2. In your AppComponent you are missing a:

    SoundsRepository soundsRepository(); 
  3. In your Global which extends Application/MultidexApplication you create your DaggerAppComponent - good

  4. In your other activities/fragments/services just call:

    Global application = (Global) getApplication(); SoundsRepository sr = application.getComponent().soundsRepository() 

Android guarantees you have only one instance of your Application (Global) class for all other actvities/services (its somewhat like a singleton).

So keep your component in that application class, and whenever you need your class, call: (YourApplication) getApplication().getComponent().yourSingleInstanceSomething();

I created and tested sample code for you: https://github.com/zakrzak/StackDaggerTest

Dagger's @Singleton is just a scope, and does not guarantee returning a singular instance of a class.

In my understanding, if you:

void inject(PostView postView); 

you tell Dagger to make everything you annotated with @Provided in AppModule accessible in your PostView as soon as you request it with:

@Inject SoundsRepository soundsRepository; 

then dagger just calls the @provided method which in your case returns a new SoundRepository instance:

@Singleton @Provides SoundsRepository provideSoundsRepository(Context ........) {     return new SoundsRepository(...); } 

which causes your problem

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment