Reputation: 7040
I am trying to inject Context
using Dagger 2.
AppComponent.kt:
@Singleton
@Component(
modules = [
AppModule::class
]
)
interface AppComponent {
fun context(): Context
}
AppModule.kt:
@Module
class AppModule(private val application: Application) {
@Provides
@Singleton
fun providesApplicationContext(): Context = application
}
MainApp.kt:
class MainApp : Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = initDagger()
}
private fun initDagger() = DaggerAppComponent.builder()
.appModule(AppModule(this))
.build()
}
Manager.kt: (Class where I want to inject Context
)
object Manager {
@Inject
lateinit var context: Context
}
However, I am getting following error:
error: Dagger does not support injection into static fields
public static android.content.Context context;
^
Is this because I am using an object
(Singleton)?
If you have any doubts related to question, please comment below. Thank you.
Upvotes: 4
Views: 8218
Reputation: 96
https://dagger.dev/dagger-1-migration.html
Dagger 2 does not support static injection
You may try something like
object Test {
var context: Context = MainApp.getComponent().context()
}
Do not place Android context classes in static fields as it's a memory leak.
So, You may also try creating a Wrapper around the context and provide dependencies as others suggested.
Upvotes: 1
Reputation: 111
It's because you are not injecting your Manager class in your AppModule.kt and also you need to pass the context.
Just like this:
@Module
class AppModule(private val application: Application) {
@Singleton
@Provides
fun providesManager(): Manager {
return Manager(application.applicationContext)
}
}
Obviously you need to change your Manager class to:
@Singleton
class Manager @Inject constructor(context: Context) {
//here you can use your context
}
And it should work
Additional:
You can remove this line in your AppComponent.kt:
fun context(): Context
Because it is not necessary and unused
the only disadvantage its that you will need to inject your Manager class in every activity/fragment you want to use it
Just like @jsamol said
Upvotes: 1
Reputation: 3232
Is this because I am using an
object
(Singleton)?
Yes, object
s' properties are Java's static fields under the hood. Your Manager
class would decompile to something similar to:
public final class Manager {
@Inject
@NotNull
public static Context context;
public static final Manager INSTANCE;
static {
INSTANCE = new Manager();
}
private Manager() {
}
@NotNull
public final Context getContext() {
return context;
}
public final setContext(Context var1) {
context = var1;
}
}
and Dagger 2 simply does not support injection into static fields
. However, even if Dagger let you do it, the dependency wouldn't be satisfied. That's because Dagger won't be able to inject into an object unless is explicitly told to do so (like you do when injecting for example into activities) or creates the object by itself. Obviously the latter doesn't apply when it comes to Kotlin's object
s. In order to ask Dagger to inject the dependency you would have to somehow provide a MainApp
instance:
init {
mainApp.appComponent.inject(this)
}
which doesn't make much sense since you'd like to inject it (as a Context
) in the first place.
Therefore you have to either satisfy the dependency manually and don't bother with Dagger in this one or leave the object
idea behind, use just a standard class and let Dagger handle its scope:
@Singleton
class Manager @Inject constructor(private val context: Context) {
}
The only drawback is that you would have to inject a Manager
instance (created by Dagger) into every class that needs to use it instead of calling its methods statically.
Upvotes: 3