Daniel Weidensdörfer
12/23/2024, 2:20 PMeygraber
12/24/2024, 2:54 AM@Component
a lot because the docs showed things like RealNetworkComponent
.
However, structuring your component hierarchy like that means that other parent components of AppComponent
wouldn't be able to inject anything from RealNetworkComponent
.
My solution to that (and answer to @Daniel Weidensdörfer) has been to use a hierarchy of AppComponent
, ActivityComponent
and ScreenComponent
, with a corresponding scope for each one (obviously an Android solution, but the concept extends to any other system).
Instead of having a NetworkComponent
I declare a NetworkModule
interface and have the appropriate component implement it (or more recently just use kotlin-inject-anvil and ContributesTo
).Daniel Weidensdörfer
12/24/2024, 1:30 PMdomain
, data
, feature1
, feature2
, app
modules. With obvious dependencies data
<- `domain`<- features
<- app
.
Currently I have a component for each of the gradle modules. Since there is no "Master" component that contains everything, each feature gets its references from its own component FeatureXComponent which in turn reference the DomainComponent (if needed).
The DomainComponent cannot be a "Module" interface as two different trees would be generated for each child feature.
So with this architecture, I'm creating a new scope XXXSingleton for each component. While I'm asking myself why there is no global Singleton annotation provided by the framework.Marcelo Gobetti
05/02/2025, 9:51 PM@Component abstract class
path.
there are a few drawbacks with using interfaces, especially when `internal`s are involved (to Daniel's point on modularization), but after some time trying your idea out:
a hierarchy ofI finally got to a place that feels familiar with other projects, and while boilerplate exists in different forms, it's smaller and easier to handle than the other options, it seems. ------ @Daniel Weidensdörfer thank you for the original post, I had the same question and struggle, and was going the same route of components being 1:1 with gradle modules. I think what Eliezer is suggesting is we wouldn't have `@Component`s per module, but interfaces, and then only a few "master" components that implement them: those 3 he pointed out (where I understand,AppComponent
andActivityComponent
ScreenComponent
ScreenComponent
means N of those for N screens, i.e. HomeScreenComponent
, SettingsScreenComponent
etc.)
by having fewer components, you automatically have fewer scopes, as all the interfaces implemented by 1 component can use that 1 scope
@ApplicationScope
@Component
abstract class ApplicationComponent(
@get:Provides val context: Context
) : DataComponent, NetworkComponent
...
@ActivityScope
@Component
abstract class ActivityComponent(
@Component val applicationComponent: ApplicationComponent
) : InAppReviewComponent, SplashScreenComponent
...
@HomeScreenScope
@Component
abstract class HomeScreenComponent(
@Component val activityComponent: ActivityComponent
) : HomeStuffComponent
this is one of the repos that helped shape my ideas. While learning, I like to start simple, so it's been helpful to me that it doesn't use Anvil, which would be another thing for me to learn from zero