@Produces 之后@Injects?
@Injects after @Produces?
我正在尝试通过 Dagger 2 学习 DI 并将其应用到我们的产品中。用 @Singleton
注释的应用程序级别的东西非常简单(例如 SharedPreferences
)。在考虑我们的架构时,有几个本质上是异步的依赖项,我想象它们的范围在 @ForSession
范围内。
- 我们的认证token/account信息,从Android
AccountManager
获取。在现有有效会话的情况下可以是同步的。如果没有现有会话并且 AccountManager
必须显示完整的登录流程,则可能是异步的。
- 一旦我们有了有效的会话令牌和会话信息:
- 提供
Endpoint
来满足依赖关系,以便我们的网络层知道在哪里可以找到 API。
- 从网络"user"获取我们的"user"信息API。
- 从网络API(或本地缓存)中提取额外的支持信息。
- 从网络 API(或本地缓存)中拉取本地化的后端字符串。
- 让依赖于绑定的组件运行
Service
。仅当绑定 Service
绑定完成时才异步提供该组件。
表示层应在收到这些项目的集合时进行控制。除了某种 "loading" 显示,如果没有上述任何一项,它就无能为力了。
感觉这些依赖项适合 @ProducerModule
和 @Produces
的用例。我觉得我可以为这些依赖项中的每一个提供 @Produces ListenableFuture<>
方法,也许 SettableFuture<>
作为实现。执行任何需要的工作,在那个未来调用 set()
,满足依赖性。
我对 Producers guide.
中的这句话感到不安
As in the above example, producer modules can be used seamlessly with ordinary modules, subject to the restriction that provided types cannot depend on produced types.
对于 "gate presentation on everything being available" 我可以设想一个复合对象,它可以得到 @Inject
和未包装的 T
期货。但这合法吗?
这是我最接近的一次,但它显式调用了组合的构造函数,而不是注入它。有没有办法做这个清洁剂?
@ProducerModule
public class SessionModule {
@Produces
@ForSession
static ListenableFuture<User> produceSignedInUser(SessionManager sessionManager) {
return sessionManager.getSignedInUserFuture();
}
@Produces
@ForSession
static ListenableFuture<BoundService> produceBoundService(SessionManager sessionManager) {
return sessionManager.getBoundServiceFuture();
}
@Produces
@ForSession
static CompositeSessionInfo produceComposite(User user, BoundService service) {
return new CompositeSessionInfo(user, service);
}
}
然后组件:
@ForSession
@ProductionComponent(modules = SessionModule.class)
public interface SessionComponent {
ListenableFuture<CompositeSessionInfo> getCompsiteSessionInfoFuture();
}
在我想进入的某个地方,我可以做类似的事情:
SessionComponent component = Dagger_SessionComponent.builder()
.executor(executor)
.build();
Futures.addCallback(component.getCompsiteSessionInfoFuture(),
new FutureCallback<CompositeSessionInfo> {
public void onSuccess(CompositeSessionInfo result) {
releaseTheHounds(result);
}
public void onFailure(Throwable t) {
reportError(t);
}
});
我对这部分的理解有偏差吗?顺便说一句:为什么 @Produces
方法声明为 static
?这是必需的吗? (编辑:static
肯定不是必需的,但我不确定除了 Module
中没有实例字段之外的意图是什么。
编辑:
我决定创建一个 proof of concept project 来从我的实际项目中抽象出我的想法。一切都如我所愿 除了 我无法 @Inject
我的任何 @Produce
d 项目,最终结果 "composite" 数据或中间结果。如果我在组件中公开一个 getter,我就可以获得它们,这就是我所做的。
我目前的计划是将这个基于 @Producer
的异步内容放在一个单独的可注入模块中,然后将生成的依赖项输入到一个 @Provides
风格的模块中,该模块在其他地方提供,以便它们可以成为 @Inject
ed.
编辑编辑:
更新了概念证明,使其具有共同的前体依赖性,从而更接近地模仿我的需求。仍然不能@Inject。我相信这和我得到的一样好。
好吧,看来我要单干了,我会 post 我的最终结论作为我自己的答案,希望能帮助其他想做类似事情的人。
我又更新了一次proof of concept project。现在,一旦满足所有异步依赖项,新的单一复合依赖项 是一个实际的 @Module,@Produced
由新重命名的 SessionProductionComponent
,那么该模块就是注册为名为 SessionProvisionComponent
的组件。这个组件是一个标准的 @Component
和 @Provide
方法,通过标准的 @Inject
机制提供依赖。
@Produces
@ForSession
public SessionProvisionModule produceSessionProvisionModule(Application app, SomeAsyncDependency someAsyncDependency, AnotherAsyncDependency anotherAsyncDependency) {
SessionProvisionModule module = new SessionProvisionModule(someAsyncDependency, anotherAsyncDependency);
((App) app).createSessionProvisionComponent(module);
return module;
}
现在在MainActivity
中,当我需要获取会话信息时,它看起来像这样:
App app = (App) getApplication();
sessionProductionComponent = app.getSessionProductionComponent();
if (app.getSessionProductionComponent() == null) {
sessionProductionComponent = app.createSessionProductionComponent(new SessionProductionModule());
}
Futures.addCallback(sessionProductionComponent.getSessionProvisionModuleFuture(),
new FutureCallback<SessionProvisionModule>() {
@Override
public void onSuccess(SessionProvisionModule result) {
app.getSessionProvisionComponent().inject(MainActivity.this);
}
@Override
public void onFailure(Throwable t) {
// handle failure
}
});
一旦 Future
成功,我就可以 inject()
MainActivity
并且任何带注释的字段都会像预期的那样获得 @Injected
和依赖项。
这样,我在@Produce
之后居然可以有@Inject
了。
没有我想要的那么干净,但仍然比没有 DI 好。现在,可以以任何顺序满足任意数量的异步依赖项,在任何时间范围内运行,并且一旦所有这些都准备就绪,就会设置一个 Future
并准备好 SessionProvisionComponent
来注入依赖项 @Produced
依赖关系。
很开心。
我正在尝试通过 Dagger 2 学习 DI 并将其应用到我们的产品中。用 @Singleton
注释的应用程序级别的东西非常简单(例如 SharedPreferences
)。在考虑我们的架构时,有几个本质上是异步的依赖项,我想象它们的范围在 @ForSession
范围内。
- 我们的认证token/account信息,从Android
AccountManager
获取。在现有有效会话的情况下可以是同步的。如果没有现有会话并且AccountManager
必须显示完整的登录流程,则可能是异步的。 - 一旦我们有了有效的会话令牌和会话信息:
- 提供
Endpoint
来满足依赖关系,以便我们的网络层知道在哪里可以找到 API。 - 从网络"user"获取我们的"user"信息API。
- 从网络API(或本地缓存)中提取额外的支持信息。
- 从网络 API(或本地缓存)中拉取本地化的后端字符串。
- 让依赖于绑定的组件运行
Service
。仅当绑定Service
绑定完成时才异步提供该组件。
- 提供
表示层应在收到这些项目的集合时进行控制。除了某种 "loading" 显示,如果没有上述任何一项,它就无能为力了。
感觉这些依赖项适合 @ProducerModule
和 @Produces
的用例。我觉得我可以为这些依赖项中的每一个提供 @Produces ListenableFuture<>
方法,也许 SettableFuture<>
作为实现。执行任何需要的工作,在那个未来调用 set()
,满足依赖性。
我对 Producers guide.
中的这句话感到不安As in the above example, producer modules can be used seamlessly with ordinary modules, subject to the restriction that provided types cannot depend on produced types.
对于 "gate presentation on everything being available" 我可以设想一个复合对象,它可以得到 @Inject
和未包装的 T
期货。但这合法吗?
这是我最接近的一次,但它显式调用了组合的构造函数,而不是注入它。有没有办法做这个清洁剂?
@ProducerModule
public class SessionModule {
@Produces
@ForSession
static ListenableFuture<User> produceSignedInUser(SessionManager sessionManager) {
return sessionManager.getSignedInUserFuture();
}
@Produces
@ForSession
static ListenableFuture<BoundService> produceBoundService(SessionManager sessionManager) {
return sessionManager.getBoundServiceFuture();
}
@Produces
@ForSession
static CompositeSessionInfo produceComposite(User user, BoundService service) {
return new CompositeSessionInfo(user, service);
}
}
然后组件:
@ForSession
@ProductionComponent(modules = SessionModule.class)
public interface SessionComponent {
ListenableFuture<CompositeSessionInfo> getCompsiteSessionInfoFuture();
}
在我想进入的某个地方,我可以做类似的事情:
SessionComponent component = Dagger_SessionComponent.builder()
.executor(executor)
.build();
Futures.addCallback(component.getCompsiteSessionInfoFuture(),
new FutureCallback<CompositeSessionInfo> {
public void onSuccess(CompositeSessionInfo result) {
releaseTheHounds(result);
}
public void onFailure(Throwable t) {
reportError(t);
}
});
我对这部分的理解有偏差吗?顺便说一句:为什么 @Produces
方法声明为 static
?这是必需的吗? (编辑:static
肯定不是必需的,但我不确定除了 Module
中没有实例字段之外的意图是什么。
编辑:
我决定创建一个 proof of concept project 来从我的实际项目中抽象出我的想法。一切都如我所愿 除了 我无法 @Inject
我的任何 @Produce
d 项目,最终结果 "composite" 数据或中间结果。如果我在组件中公开一个 getter,我就可以获得它们,这就是我所做的。
我目前的计划是将这个基于 @Producer
的异步内容放在一个单独的可注入模块中,然后将生成的依赖项输入到一个 @Provides
风格的模块中,该模块在其他地方提供,以便它们可以成为 @Inject
ed.
编辑编辑:
更新了概念证明,使其具有共同的前体依赖性,从而更接近地模仿我的需求。仍然不能@Inject。我相信这和我得到的一样好。
好吧,看来我要单干了,我会 post 我的最终结论作为我自己的答案,希望能帮助其他想做类似事情的人。
我又更新了一次proof of concept project。现在,一旦满足所有异步依赖项,新的单一复合依赖项 是一个实际的 @Module,@Produced
由新重命名的 SessionProductionComponent
,那么该模块就是注册为名为 SessionProvisionComponent
的组件。这个组件是一个标准的 @Component
和 @Provide
方法,通过标准的 @Inject
机制提供依赖。
@Produces
@ForSession
public SessionProvisionModule produceSessionProvisionModule(Application app, SomeAsyncDependency someAsyncDependency, AnotherAsyncDependency anotherAsyncDependency) {
SessionProvisionModule module = new SessionProvisionModule(someAsyncDependency, anotherAsyncDependency);
((App) app).createSessionProvisionComponent(module);
return module;
}
现在在MainActivity
中,当我需要获取会话信息时,它看起来像这样:
App app = (App) getApplication();
sessionProductionComponent = app.getSessionProductionComponent();
if (app.getSessionProductionComponent() == null) {
sessionProductionComponent = app.createSessionProductionComponent(new SessionProductionModule());
}
Futures.addCallback(sessionProductionComponent.getSessionProvisionModuleFuture(),
new FutureCallback<SessionProvisionModule>() {
@Override
public void onSuccess(SessionProvisionModule result) {
app.getSessionProvisionComponent().inject(MainActivity.this);
}
@Override
public void onFailure(Throwable t) {
// handle failure
}
});
一旦 Future
成功,我就可以 inject()
MainActivity
并且任何带注释的字段都会像预期的那样获得 @Injected
和依赖项。
这样,我在@Produce
之后居然可以有@Inject
了。
没有我想要的那么干净,但仍然比没有 DI 好。现在,可以以任何顺序满足任意数量的异步依赖项,在任何时间范围内运行,并且一旦所有这些都准备就绪,就会设置一个 Future
并准备好 SessionProvisionComponent
来注入依赖项 @Produced
依赖关系。
很开心。