I'm implimenting Dagger 2
in my Android app. I have it setup in the following way:
AppComponent.java
@Singleton
@Component(modules = {
AndroidInjectionModule.class,
AndroidSupportInjectionModule.class,
ActivityBuilder.class,
AppModule.class,
DataBaseDaoModule.class
})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application aApplication);
AppComponent build();
}
Application application();
void inject(MyApplication aApplication);
}
AppInjector.java
ublic class AppInjector {
public static void init(MyApplication aApplication) {
//Initialize dagger and inject the aApplication
DaggerAppComponent.builder().application(aApplication).build().inject(aApplication);
aApplication.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity aActivity, Bundle aBundle) {
handleActivity(aActivity);
}
@Override
public void onActivityStarted(Activity aActivity) {
}
@Override
public void onActivityResumed(Activity aActivity) {
}
@Override
public void onActivityPaused(Activity aActivity) {
}
@Override
public void onActivityStopped(Activity aActivity) {
}
@Override
public void onActivitySaveInstanceState(Activity aActivity, Bundle aBundle) {
}
@Override
public void onActivityDestroyed(Activity aActivity) {
}
});
}
private static void handleActivity(Activity aActivity) {
if (aActivity instanceof HasActivityInjector) {
AndroidInjection.inject(aActivity);
Timber.d("injected Activity");
}
if (aActivity instanceof FragmentActivity) {
((FragmentActivity) aActivity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(
new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f,
Bundle savedInstanceState) {
if (f instanceof Injectable) {
Timber.d("injected Fragment");
AndroidSupportInjection.inject(f);
}
}
}, true);
}
}
}
AppModule.java
Module(includes = ViewModelModule.class)
class AppModule {
@Singleton
@Provides
ApiService providesApiService(OkHttpClient aClient, MyInterceptor aInterceptor) {
//Build a Retrofit object here
}
@Singleton
@Provides
OkHttpClient providesOkHTTPClient(MyInterceptor aInterceptor) {
//Setup OKHTTP here
}
}
And finally in MyApplication.Java in the onCreate
method I just call the AppInjector
like so: AppInjector.init(this);
All of this works and anything I put in my AppComponent's moduels, I can inject into Activities, Fragments and ViewModels
.
However, I have cases where I would need a utility
class, that depends on Application
, for contex
- and I use the utility class in various places. Or I will have a Manager
class, that depends on Application, or needs something from AppModule. However, since I use these classes outside of Activities, Fragments and ViewModels
I cannot just inject. How would I provide my utility
classes with their dependencies and any other type of class - like a manager class?
My first thought was to create a UtilityComponent
and a ManagerCompoent
of sorts, however I have no idea how I would get them to work with anything in AppModuel
or through my AppComponent
.
Please don't just use
component.inject(myObject)
for everything. Always prefer constructor injection or provide it from a module where you can do additional setup steps..inject(myObject)
is intended for Framework components where you don't have access to the constructor.You don't need a separate component for that. See below.
That has nothing to do with injection. You're talking about scopes, and it sound like your utilities are a
@Singleton
. YourAppComponent
is a@Singleton
scoped component, hence it can be used to provide your utils, too.If they are part of the
@Singleton
component, which has access to your Application, they can also be provided anywhere else. No need for more components or anything. Just declare your dependencies and don't overthink it.Just declare your util, annotate it with
@Singleton
and mark the constructor with@Inject
for constructor injection.@Singleton
ensures that it will be provided by yourAppComponent
and can access theApplication
on which it depends.And then you can just inject it in your Activities, Fragments, or even into other Utilities....
And you can inject either or both into your activity or fragment...
You do not need any modules, provides methods, or components to provide simple classes. Just make sure to add the right scope!