I have been working with Dagger 2 for a while and I m still trying to figure some things out. One thing that I still don`t manage very good is setting up modules and components for different situations, like an activity with several fragments. I have seen a lot of implementations and most of the time it is a bit different.
So, let me expose my current app structure which uses MVP and I would like some opinions if my implementation is ok or not.
@Module
public final class ApplicationModule {
private Context mContext;
public ApplicationModule(Context context){
mContext = context;
}
public ApplicationModule(){
mContext = null;
}
@Provides
Context provideContext(){
return mContext;
}
@Singleton
@Provides
public SharedPreferences getAppPreferences(){
return mContext.getSharedPreferences("CalorieApp",Context.MODE_PRIVATE);
}
}
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(MainApplication mainApplication);
SharedPreferences sharedPreferences();
}
In this AppModule I will usually set only Singleton that my app will need. Like SharedPreferences or anything related to network requests. This Module and Component are somehow standard and I always start my apps with creating them like this.
Then I set my module and component for Activity which will have a dependencie on ApplicationComponent
@Module
public class ActivityModule {
private Activity activity;
public ActivityModule(Activity activity){
this.activity = activity;
}
@Provides
Activity provideActivity(){
return activity;
}
}
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules =
ActivityModule.class)
public interface ActivityComponent {
void inject(WelcomeActivity welcomeActivity);
void inject(MainActivity mainActivity);
}
Now, MainActivity has 3 fragments and I will create 3 modules for fragments and 1 component
@Module
public class HomeFragmentModule {
private HomeFragmentContract.View mView;
public HomeFragmentModule(HomeFragmentContract.View view){
mView = view;
}
@Provides
HomeFragmentContract.View provideHomeFragmentView(){
return mView;
}
}
@Module
public class ChartsFragmentModule {
private ChartsFragmentContract.View mView;
public ChartsFragmentModule(ChartsFragmentContract.View view){
mView = view;
}
@Provides
ChartsFragmentContract.View provideChartsFragmentView(){
return mView;
}
}
@Module
public class ProfileFragmentModule {
private ProfileFragmentContract.View mView;
public ProfileFragmentModule(ProfileFragmentContract.View view){
mView = view;
}
@Provides
ProfileFragmentContract.View provideProfileFragmentContract(){
return mView;
}
}
@PerFragment
@Component(dependencies = ActivityComponent.class ,
modules = {ChartsFragmentModule.class, HomeFragmentModule.class,
ProfileFragmentModule.class})
public interface FragmentComponent {
void inject(ChartsFragment chartsFragment);
void inject(HomeFragment homeFragment);
void inject(ProfileFragment profileFragment);
}
Then I will have to instantiate Dagger, first in my application class and then in each of the activities and fragments
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
For example in WelcomeActivity, I instantiate it like this:
DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.applicationComponent(((MainApplication)
getApplication()).getApplicationComponent())
.build()
.inject(this);
In MainActivity I do it same as above, but I`m creating a getter for activity component inside it.
Then in each of my fragments I instantiate like this:
DaggerFragmentComponent.builder()
.homeFragmentModule(new HomeFragmentModule(this))
.activityComponent(((MainActivity)getActivity()).getActivityComponent())
.build()
.inject(this);
At this point everything works fine. I can inject Presenters and anything I want, but I`m not sure if it is the correct approach.
What do you think of my implementation?
Also I have one Repository class that will be used in every Presenter to display information from Firebase to the UI .
Would you create a component and module just for that and then make all the fragments have a dependency to it?
Hope I did not ask too many questions, but I would really like to clean my ideas.
Thank you