英文:
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<Key, ExpensiveObject> 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<A>
, so instead of having a Map<K, A>
you can have a Map<K, Provider<A>>
. 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<Key, Provider<ExpensiveObject>> 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("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>>
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论