Yes, I know this has been asked before, and yes, I know it is "by design".
But I'd like to do something like this:
@Component(modules = {RealmModule.class})
public interface RealmComponent {
Realm realm();
}
@Component(modules = {RepositoryModule.class})
public interface RepositoryComponent {
PersonRepository personRepository();
ScheduleRepository schedulesRepository();
}
@Component(dependencies = {RealmComponent.class, RepositoryComponent.class})
public interface AppDataComponent
extends RealmComponent, RepositoryComponent {
}
@ApplicationScope
@Component(dependencies = {AppContextComponent.class,
AppDataComponent.class,
AppDomainComponent.class,
AppPresentationComponent.class,
AppUtilsComponent.class})
public interface ApplicationComponent
extends AppContextComponent, AppDataComponent, AppDomainComponent, AppUtilsComponent, AppPresentationComponent {
void inject(CustomApplication customApplication);
void inject(DashboardActivity dashboardActivity);
}
However, what I get is unscoped, every time I inject a JobManager
or a ScheduleRepository
or anything else, I get a new instance. The only way I could "fix" that was this.
@Module
public class JobManagerModule {
private JobManager jobManager;
@Provides
public JobManager jobManager(Context context) {
if(jobManager == null) {
jobManager = new JobManager(context, new Configuration.Builder(context).networkUtil(
new WifiOrMobileNetworkUtil(context)).build());
}
return jobManager;
}
}
Not a fan.
So, how is one meant to structure and rip apart the dependency tree, without making one big gigantic über blob component that has every single module listed and every single provision method (instead of these "subcomponent" component dependencies)?
I tried using subcomponents for this, but then you have to provide every single module for the final ApplicationComponent
.
I'm not sure what to do here. I tried specifying @Singleton
for every first-level component and @SubcomponentScope
for every AppDataLevelComponent
, I also tried making a new scope for every single subcomponent, but both of them failed with "cannot depend on multiple scoped components".
EDIT: Apparently in order to get scoped providers, marking the components with the scope is not enough - you must specify the scope for the @Provides
annotated methods too.
@Module
public class RepositoryModule {
@Provides
@Singleton
public PersonRepository personRepository() {
return new PersonRepositoryImpl();
}
@Provides
@Singleton
public ScheduleRepository schedulesRepository() {
return new SchedulesRepositoryImpl();
}
}
In the meantime, I ended up with this übercomponent.
@Singleton
@Component(modules = {
AppContextModule.class,
DbMapperModule.class,
DbTaskModule.class,
RealmModule.class,
RepositoryModule.class,
InteractorModule.class,
ServiceModule.class,
PresenterModule.class,
XmlPersisterModule.class
})
public interface ApplicationComponent
extends AppContextComponent, AppDataComponent, AppDomainComponent, AppUtilsComponent, AppPresentationComponent {
Where the xyzComponent
classes are just interfaces to store the provision methods...
(Please note that this structure is an anti-pattern as described by Martin Fowler, and you should organize modules based on features / activities, and make them into subscoped components using component dependencies. Component dependencies are used to subscope your superscope components, and "inherit" dependency providers.)