使用匕首柄2.42提供延迟注射

问题描述 投票:0回答:2

匕首柄

2.42

我正在尝试使用惰性匕首注入来提供此类。

class AlgoliaAnalyticsProvider @Inject constructor(
    private val clientInsights: Lazy<ClientInsights>,
    private val coroutineDispatcherProvider: CoroutineDispatcherProvider
)

在我的 AppModule 中,我有以下内容:

    @Singleton
    @Provides
    fun provideClientInsights(remoteConfigProvider: RemoteConfigProvider): Lazy<ClientInsights> {
        return lazy { ClientInsights(
            ApplicationID(BuildConfig.ALGOLIA_APP_ID),
            APIKey(remoteConfigProvider.keyAlgoliaApiKey)
        )}
    }

我在通过

AlgoliaAnalyticsProvider

的地方也有这个
   @Singleton
    @Provides
    fun provideAnalyticsProvider(
        firebaseAnalyticsProvider: FirebaseAnalyticsProvider,
        crashlyticsUserPropertiesProvider:        CrashlyticsUserPropertiesProvider,
        caMPAnalyticsProvider: CaMPAnalyticsProvider,
        algoliaAnalyticsProvider: AlgoliaAnalyticsProvider
    ) = AnalyticsProvider(
        listOf(
            firebaseAnalyticsProvider,
            crashlyticsUserPropertiesProvider,
            algoliaAnalyticsProvider
        )
    )

我不断收到此错误:

error: [Dagger/MissingBinding] kotlin.Lazy<? extends com.algolia.search.client.ClientInsights> cannot be provided without an @Provides-annotated method.
  public abstract static class SingletonC implements CDSApplication_GeneratedInjector,
                         ^
      kotlin.Lazy<? extends com.algolia.search.client.ClientInsights> is injected at
          com.centraldepartment.app.analytics.provider.AlgoliaAnalyticsProvider(clientInsights, …)
      com.centraldepartment.app.analytics.provider.AlgoliaAnalyticsProvider is injected at
          com.centraldepartment.app.analytics.AnalyticsModule.provideAnalyticsProvider(…, algoliaAnalyticsProvider, …)

但是如果我注释掉下面的代码,它似乎可以工作:

 @Singleton
        @Provides
        fun provideAnalyticsProvider(
            firebaseAnalyticsProvider: FirebaseAnalyticsProvider,
            crashlyticsUserPropertiesProvider:        CrashlyticsUserPropertiesProvider,
            caMPAnalyticsProvider: CaMPAnalyticsProvider,
  //          algoliaAnalyticsProvider: AlgoliaAnalyticsProvider
        ) = AnalyticsProvider(
            listOf(
                firebaseAnalyticsProvider,
                crashlyticsUserPropertiesProvider,
           //     algoliaAnalyticsProvider
            )
        )
dagger-2 dagger-hilt lazy-initialization
2个回答
4
投票

您需要更改 AlgoliaAnalyticsProvider 构造函数以接受

Lazy<@JvmSuppressWildcards ClientInsights>
而不是
Lazy<ClientInsights>
。这并不是关于 Lazy 的任何具体内容,只是它涉及一个
@Provides
方法,返回 Kotlin 中泛型的内容。

Java 和 Kotlin 中的泛型很棘手,如 Kotlin 泛型文档中的 “方差”部分所述。 Kotlin 提供

in
out
作为“方差注释”,比 Java 提供的 通用通配符 (
Lazy<? extends Foo>
) 更有助于推理。然而,即使没有这些方差注释,泛型也会造成足够的互操作问题,以至于 Kotlin 的默认互操作行为默认添加通配符:

为了使 Kotlin API 在 Java 中工作,当

 作为参数 
出现时,编译器将
Box<Super>
生成为
Box<? extends Super>
(对于协变定义的
Box
)(或
Foo<? super Bar>
对于逆变定义的 Foo)。当它是返回值时,不会生成通配符,因为否则 Java 客户端将不得不处理它们(这违背了常见的 Java 编码风格)。

这对于您的使用来说是没问题的 -

Lazy<? extends ClientInsights>
完全可以让您在 AlgoliaAnalyticsProvider 中获得所需的 ClientInsights 或子类 - 但如您的错误消息所示,Dagger 未能成功搜索
kotlin.Lazy<? extends ClientInsights>
的绑定并且不会接受
kotlin.Lazy<ClientInsights>
的绑定。要抑制 Kotlin 的默认行为,您需要在上面的同一互操作页面上应用解决方法:将
@JvmSuppressWildcards
添加到您的参数中。然后,您的调用站点泛型将与您的
@Provides
返回值完全匹配,并且 Dagger 将正确应用您的绑定。

通配符困难是 Dagger 使用 Kotlin 时的一个已知痛点,如 开放问题 google/dagger#2586 以及引发它的评论。文档中有一条可见的警告消息,但仅在多重绑定页面上,因为多重绑定创建的集合也面临这种危险。


需要明确的是,上面的答案是关于 Kotlin 内置函数

lazy
。另外,Dagger 有一个名为 Lazy内置包装类,它的工作方式与 Provider 非常相似,但只会在每个 Lazy 实例第一次调用
@Provides
方法或
@Inject
构造函数。对于图表中的任何绑定 T,Dagger 将自动使
Provider<T>
dagger.Lazy<T>
Provider<dagger.Lazy<T>>
可用。

这实际上可能更符合您的需求:您的

@Provides
方法将直接返回 ClientInsights,然后您可以将其注入作为您选择的 ClientInsights、
Provider<ClientInsights>
Lazy<ClientInsights>
;在内部,Dagger 还可以避免创建
Provider<kotlin.Lazy<ClientInsights>>
,因为 Dagger 可以直接返回用于强制执行您添加的 @Singleton 注释的相同内部
DoubleCheck 实现
。但是,如果您不想要能够直接注入 ClientInsights 而只注入
Lazy<@JvmSuppressWildcards ClientInsights>
,那么简单地添加注释可能是最好的方法。


0
投票

就我而言,问题在于没有使用正确的导入。

正确:

import dagger.Lazy

© www.soinside.com 2019 - 2024. All rights reserved.