Dagger 2 延迟初始化映射条目

huangapple go评论72阅读模式
英文:

Dagger 2 lazy initialize map entries

问题

我有一个如下所示的Dagger模块和组件。我希望仅在从地图中获取资源时才在模块中创建它们,而在服务启动时不创建。我尝试使用Lazy<T>进行了一些尝试,但不太清楚如何实现这一点。

@Module
public abstract class ExpensiveObjectModule {

    @Singleton
    @Provides
    @IntoMap
    @UniqueKey(Key.A)
    static ExpensiveObject provideKeyAExpensiveObject() {
        return new ExpensiveObject(Key.A);
    }

    @Singleton
    @Provides
    @IntoMap
    @UniqueKey(Key.B)
    static ExpensiveObject provideKeyBExpensiveObject() {
        return new ExpensiveObject(Key.B);
    }
}

@Singleton
@Component(modules = {
        ExpensiveObjectModule.class
})
public interface HandlerComponent {
    Map<Key, ExpensiveObject> getExpensiveObjectByKey();
}

handlerComponent.getExpensiveObjectByKey().get(key);
英文:

I have a Dagger module and component defined as below. I want to create the resources in the module only when they are being fetched from the map and not when the service comes up. I played around using Lazy<T> but not sure how to achieve this.

@Module
public abstract class ExpensiveObjectModule {

    @Singleton
    @Provides
    @IntoMap
    @UniqueKey(Key.A)
    static ExpensiveObject provideKeyAExpensiveObject() {
        return new ExpensiveObject(Key.A);
    }

    @Singleton
    @Provides
    @IntoMap
    @UniqueKey(Key.B)
    static ExpensiveObject provideKeyBExpensiveObject() {
        return new ExpensiveObject(Key.B);
    }
}
@Singleton
@Component (modules = {
        ExpensiveObjectModule.class
})
public interface HandlerComponent {
    Map&lt;Key, ExpensiveObject&gt; getExpensiveObjectByKey();

}
handlerComponent.getExpensiveObjectByKey().get(key);

答案1

得分: 1

以下是翻译好的内容:

每当您可以注入 A 时,您也可以注入 Provider<A>,因此,不必拥有 Map<K, A>,您可以拥有 Map<K, Provider<A>>。同样的方法可能适用于 Lazy,但 Provider 将尊重某物所拥有的任何范围,而 Lazy 则始终会将其缓存起来。

因此,您可以像这样返回映射:

Map<Key, Provider<ExpensiveObject>> getExpensiveObjectByKey();

一个最简示例(但使用 Kotlin)如下所示:

@MustBeDocumented
@Target(
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class Key(val value: String)

@Module
object ModFoo {

    @Provides
    @IntoMap
    @Key("foo")
    fun foo(): Any = "Foo";

    @Provides
    @IntoMap
    @Key("bar")
    fun bar(): Any = 3;
}

@Component(modules = [ModFoo::class])
interface Foo {
    val foo: Map<String, Any>;
    val fooProviders: Map<String, Provider<Any>>;
}
英文:

Whenever you can inject A you can also inject Provider&lt;A&gt;, so instead of having a Map&lt;K, A&gt; you can have a Map&lt;K, Provider&lt;A&gt;&gt;. The same would probably work with Lazy, but a Provider will respect whatever scope something has, while Lazy would always cache it.

So you could just return the map like this:

Map&lt;Key, Provider&lt;ExpensiveObject&gt;&gt; getExpensiveObjectByKey();

A minimal example (but in Kotlin) looks like this:

@MustBeDocumented
@Target(
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class Key(val value: String)

@Module
object ModFoo {

    @Provides
    @IntoMap
    @Key(&quot;foo&quot;)
    fun foo(): Any = &quot;Foo&quot;

    @Provides
    @IntoMap
    @Key(&quot;bar&quot;)
    fun bar(): Any = 3
}

@Component(modules = [ModFoo::class])
interface Foo {
    val foo: Map&lt;String, Any&gt;
    val fooProviders: Map&lt;String, Provider&lt;Any&gt;&gt;
}

huangapple
  • 本文由 发表于 2020年10月21日 07:25:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/64454626.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定