And*_*ast 11 android dependency-injection lazy-initialization dagger-2
我是Dagger 2的新手.我有这个场景,我不想在我的应用程序中注入一个对象(在演示者中,在api中)
我最初没办法提供它.在我的应用程序的某个阶段进行身份验证之后才会创建它.
来自文档http://google.github.io/dagger/
我看到Lazy加载可能是一种解决这个问题的方法,例如
@Inject
Lazy<Grinder> lazyGrinder;
Run Code Online (Sandbox Code Playgroud)
然后使用以下方法获取这样的值:lazyGrinder.get().grind();
我的问题是:
谢谢
Jef*_*ica 23
这不是一个很好的匹配Lazy
.Lazy
是一种延迟昂贵的对象初始化的好方法,但它暗示了一些你不想要或不需要的语义,特别是关于你想要的"安全交换"行为.
简而言之,Lazy是一个在本地进行memoizes的Provider包装器:
get
,Dagger永远不会创造有问题的对象.get
创建和存储对象实例.get
返回相同的实例,依此类推,无论对象是否标记为Singleton.这使得Lazy成为昂贵对象的绝佳选择,否则该对象将成为一个领域(但可能永远不会被使用).但是,如果引用可能会改变(按照您的意愿),Lazy将会让人感到困惑:它会在第一次使用时存储该值并且永远不会在本地更新,因此多个过时的副本可能会在您的应用程序中浮动什么是"正确的"价值在任何给定的时间.
从您的示例中借用Grinder,更好的解决方案包括:
使用@Provides
返回模块中的字段的方法,可以在以后更新.您需要Provider<Grinder>
为每个长期存在的对象实例注入,因为仅对Grinder的注入引用不会更新.如果你有很多短命的物体,这仍然是最好的选择.
引用是隐式单例,但没有注释,因为您自己控制实例.Dagger会getGrinder
经常调用你的方法.
@Module public class YourModule {
private Grinder grinder;
public void setGrinder(Grinder grinder) {
this.grinder = grinder;
}
@Provides public Grinder getGrinder() {
return grinder;
}
}
/* elsewhere */
YourModule module = new YourModule();
YourComponent component = DaggerYourComponent.builder()
.yourModule(module)
.build();
/* ... */
module.setGrinder(latestAndGreatestGrinder);
Run Code Online (Sandbox Code Playgroud)正如EpicPandaForce在评论中提到的,创建/绑定一个单独的GrinderHolder,GrinderController或AtomicReference对象,它提供当前实例并允许更新.这样就不可能直接注入Grinder,但是注入获取当前正确Grinder的对象是很容易和明显的.如果您的单个GrinderHolder实现在第一次请求之前不创建Grinder,那么您已经有效地创建了一个Lazy单例.
小智 5
如果在创建组件时无法提供该对象,请不要将其添加到“组件”图中!那就是要求混乱的图形依赖和不一致。对于您正在考虑的问题@Subcomponent
,更好的解决方案是一种方法,该方法允许您创建一个新组件,该组件可以继承父组件的依赖关系,还可以添加新组件。这是一个例子:
@Component
interface RegularComponent {
@AppInstanceId String appInstanceId(); // unique per app install; not related to logging in
AuthenticatedComponent newAuthenticatedComponent();
}
@Subcomponent
interface AuthenticatedComponent {
Set<Friend> friends();
@AccountId String accountId();
}
Run Code Online (Sandbox Code Playgroud)
在此,@AccountId
子组件中的可以使用appInstanceId
提供帐户ID(如果需要),因为子组件与其父组件共享依赖项。
如果您需要为子组件的模块提供状态(带有accountId,auth令牌等),请随时将其作为参数传递给@Module
并将其存储在private final
字段中。您可以在文档中阅读有关如何提供子组件模块的更多信息。
归档时间: |
|
查看次数: |
14361 次 |
最近记录: |