According to tutorials like this one: in Dagger2 we are able to provide local singleton objects using a custom scope.
I already have a global appComponent and my goal is to create a activity scope that allows a subcomponent to have local singleton providers.
My issue is when i create a custom scope and inject my activity twice, i see that the object being provided is not the same one, even though i tagged it with the custom scope. for the appComponent which uses the @Singleton annotation it works fine though. Lets take a look at how i did this:
Here is the custom activity scope:
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
And here is how i define the subcomponent:
@ActivityScope
@Subcomponent(modules = {PresenterModule.class, UseCaseModule.class})
public interface ActivitySubComponent {
void inject(LoginActivity target);
void inject(LoginPresenter target);
void inject(UCGetFireBaseAccount target);
}
Notice here that i've tagged this subcomponent with @ActivityScope annotation that i custom made above. Now lets see the appComponent which is the parent component and global:
@Singleton
@Component(modules = {AppModule.class, NetworkModule.class, RepositoryModule.class})
public interface AppComponent {
void inject(myappCloudRepo target);
void inject (FireBaseCloudRepo target);
ActivitySubComponent plus(PresenterModule presenterModule, UseCaseModule useCaseModule);
}
Notice ActivitySubComponent is defined here as a subcomponent.
Finally lets look at the presenterModule class to see what i wanted to be provided as a singleton:
@Module
public class PresenterModule {
@Provides
@ActivityScope
LoginPresenter provideLoginPresenter(Context context) {
return new LoginPresenter(context);
}
}
Now when i actually use this i set it up in my application class like this:
public class MyApplication extends Application {
private AppComponent appComponent;
@Override
public void onCreate() {
super.onCreate();
appComponent = initDagger(this);
}
public AppComponent getAppComponent() {
return appComponent;
}
protected AppComponent initDagger(MyApplication application) {
return DaggerAppComponent.builder()
.appModule(new AppModule(application))
.build();
}
public ActivitySubComponent getActivityComponent() {
return appComponent.plus(new PresenterModule(),new UseCaseModule());
}
}
Then lastly in any activity i do this:
public class LoginActivity extends AppCompatActivity{
ActivitySubComponent activityComponent;
//this loginpresenter is from the activitysubcomponent
@Inject
LoginPresenter loginPresenter;
//this retrofit object is from the appcomponent
@Inject
Retrofit retrofit;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityComponent= ((MyApplication)getApplication()).getActivityComponent();
activityComponent.inject(this);
Log.d("j2emanue",loginPresenter.toString());
Log.d("j2emanue",retrofit.toString());
activityComponent= ((MyApplication)getApplication()).getActivityComponent();
activityComponent.inject(this);
Log.d("j2emanue2",loginPresenter.toString());
Log.d("j2emanue2",retrofit.toString());
}
}
When i take a look at the logs after injecting TWICE i am expecting all objects to be the same but instead the loginPresenter is another instance but the retrofit is the same so that works. Here is the log:
05-23 23:33:35.617 31298-31298/com.myapp.mobile.myappfashion D/j2emanue: com.myapp.mobile.myappfashion.UI.Presenters.LoginPresenter@1c27a460
05-23 23:33:35.617 31298-31298/com.myapp.mobile.myappfashion D/j2emanue: retrofit2.Retrofit@13366d19
05-23 23:33:35.617 31298-31298/com.myapp.mobile.myappfashion D/j2emanue2: com.myapp.mobile.myappfashion.UI.Presenters.LoginPresenter@3dc041de
05-23 23:33:35.617 31298-31298/com.myapp.mobile.myappfashion D/j2emanue2: retrofit2.Retrofit@13366d19
Notice the loginpresenter is another object so its not making a local singleton for me that would only be destroyed when i dereference the activitysubcomponent. what am i missing here ? The reason i want it to be a local singleton is for configuration changes. This way the presenter can be maintained during a config change.