Dagger 2 在 Kotlin 对象中注入上下文

Dagger 2 Inject Context in Kotlin Object

我正在尝试使用 Dagger 2 注入 Context

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 我要注入的地方 Context)

object Manager {

    @Inject
    lateinit var context: Context
}

但是,我收到以下错误:

error: Dagger does not support injection into static fields
    public static android.content.Context context;
                                          ^

这是因为我使用的是 object(单例)吗? 如果您对问题有任何疑问,请在下面发表评论。谢谢。

Is this because I am using an object (Singleton)?

是的,objects 的属性是 Java 的静态字段。您的 Manager class 将反编译为类似于以下内容的内容:

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;
    }
}

而 Dagger 2 只是 does not support injection into static fields。然而,即使 Dagger 让你这样做,依赖性也不会得到满足。那是因为 Dagger 将无法注入到一个对象中,除非被明确告知这样做(就像你在注入到活动中时所做的那样)或自己创建对象。显然后者不适用于 Kotlin 的 objects。为了让 Dagger 注入依赖项,你必须以某种方式提供一个 MainApp 实例:

init {
    mainApp.appComponent.inject(this)
}

这没有多大意义,因为您想首先注入它(作为 Context)。

因此,您必须手动满足依赖关系并且不要在这个中使用 Dagger 或将 object 想法抛在脑后,仅使用标准 class 并让 Dagger 处理其范围:

@Singleton
class Manager @Inject constructor(private val context: Context) {

}

唯一的缺点是您必须将一个 Manager 实例(由 Dagger 创建)注入到每个需要使用它的 class 中,而不是静态调用它的方法。

这是因为你没有在你的 AppModule.kt 中注入你的经理 class 并且你还需要传递上下文。

就像这样:

@Module
class AppModule(private val application: Application) {

    @Singleton
    @Provides
    fun providesManager(): Manager {
        return Manager(application.applicationContext)
    }
} 

显然您需要将您的经理 class 更改为:

@Singleton
class Manager @Inject constructor(context: Context) {
    //here you can use your context
}

它应该可以工作

补充:

您可以在 AppComponent.kt 中删除此行:

fun context(): Context

因为没有必要也没有用

唯一的缺点是您需要在每个 activity/fragment 中使用您的管理器 class

就像@jsamol说的

https://dagger.dev/dagger-1-migration.html

Dagger 2 does not support static injection

你可以试试

object Test {
    var context: Context = MainApp.getComponent().context()
}

不要将 Android 上下文 类 放在静态字段中,因为这是内存泄漏

因此,您也可以尝试围绕上下文创建包装器并按照其他人的建议提供依赖项。