I have an Anvil related question. It supports bind...
# squarelibraries
e
I have an Anvil related question. It supports binding for public types only. IMO this defeats the purpose of binding an implementation to an abstraction. I want the abstraction to be public but not the implementation. Anvil forces me to declare the abstraction as public. It seems if the Dagger module is generated in the same package the implementation was declared it should be possible to support at least internal? Appreciate your help with this.
z
The problem is not anvil but rather dagger. You still end up with a public generated factory for the injected implementation type
e
A public generated factory isn't too terrible though, it's generated code so "regular" code would not reference it since it doesn't exist yet when that code is written (the DaggerComponent being the exception). With Anvil we have the public class before code is generated.
z
the public generated factory exposes the injected type in its public API, so the injected type must also be public
doesn't really matter whether "regular" code touches it, the compiler doesn't differentiate
I'd encourage you to try manually writing out what you're proposing and you'd better understand why it's not possible
e
Thanks for your input. I think this isn't really Dagger's fault. The way the binds are declared in Kotlin, prevents it from compiling in the first place (even if it's just input for codegen). Would you agree that if the syntax to define a Dagger module changes (e.g. using some Dagger DSL instead of the current Dagger modules/component syntax), then being able to declare the implementation non-public is possible?
z
we could make
bindFeature
internal
but that adds basically no value since FeatureImpl must still be public anyway
dagger will generate a
FeatureImpl_Factory
that is public and exposes
FeatureImpl
and all its dependencies in its public API. You can't make
FeatureImpl
internal anyway, so visibility golfing a binds function isn't going to make any real difference for your goals of limiting access in user code
e
if if you use @Provides then
FeatureImpl
can be internal or even private, that shows it's really not a Dagger limitation
z
no, it can't
Unless FeatureImpl isn't an injected type or solely created via some
provides()
somewhere rather than constructor injection, which we don't reasonably know for certain at compile-time
at that point, if you're defining it via provides() anyway, then you don't need to use contributesbinding because you control that provider function return type anyway
e
This compiles and runs
Copy code
@Module
public object FeatureModule {
    @Provides
    public fun bindFeature(): Feature = FeatureImpl()
}

private class FeatureImpl @Inject constructor(): Feature {
factory is Java which doesn't check whether
FeatureImpl
is private or not
Copy code
public final class FeatureImpl_Factory implements Factory<FeatureImpl> {
If I do the binds in Java, Lint complains but the code compiles without issues
z
anvil generates dagger factories in kotlin
Sorry but you are going to have to take no for an answer. The layers of caveats you’ve brought up only further demonstrate why this proposal does not make sense.
2
e
I think the request makes sense but the fact that Anvil creates Kotlin code is a showstopper. If I use
generateDaggerFactories.set(false)
I can use a private implementation because Dagger creates Java code which doesn't have that limitation. Even if this isn't a solution, I at least understand now why the limitation exists. Thanks for your help!