简体   繁体   中英

Dagger 2 Inject Context in Kotlin Object

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.

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM