@Produces后@Injects?

时间:2016-02-25 02:56:20

标签: android dagger-2

我试图通过Dagger 2学习DI并将其应用到我们的产品中。使用@Singleton注释的应用程序级别的内容非常简单(例如SharedPreferences)。在考虑我们的体系结构时,有几个本质上是异步的依赖项,我想象的是@ForSession作用域范围。

  • 我们的身份验证令牌/帐户信息,从Android AccountManager获取。在现有的有效会话的情况下可以是同步的。如果没有现有会话且AccountManager必须显示完整的登录流程,则可以是异步的。
  • 获得有效的会话令牌和会话信息后:
    • 提供Endpoint以实现依赖关系,以便我们的网络层知道在哪里找到API。
    • 获取我们的用户"来自网络API的信息。
    • 从网络API(或本地缓存)中提取其他支持信息。
    • 从网络API(或本地缓存)中提取本地化的后端字符串。
    • 获取依赖于绑定Service的组件。仅在绑定的Service绑定完成时异步提供该组件。

表单层应该在收到这些项目的集合时进行门控。除了某种" loading"显示,如果没有以上任何一项,它就无法做到。

感觉这些依赖项符合@ProducerModule@Produces的用例。我觉得我可以为每个依赖项都有@Produces ListenableFuture<>个方法,可能有一个SettableFuture<>作为实现。执行所需的任何工作,在未来调用set(),满足依赖性。

我感到厌倦的是Producers guide中的引用。

  

如上例所示,生产者模块可以与普通模块无缝地使用,但受限于提供的类型不能依赖于生成的类型。

关于所有可用的&#34;门演示&#34;我可以设想一个复合对象,它可以通过未解开的@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项,无论是最终结果还是#34;复合& #34;数据或中间结果。如果我在组件中暴露一个吸气剂,我可以得到它们,这就是我所做的。

我目前的计划是在一个单独的可注入模块中关闭这个基于@Producer的异步函数,然后将结果依赖项送入@Provides样式模块,该模块将在其他地方提供,以便它们可以{ {1}}编

编辑编辑:

更新了概念证明,使其具有共同的前兆依赖性,以更接近地模仿我的需求。仍然不能@Inject。我相信这和我一样好。

1 个答案:

答案 0 :(得分:1)

好吧,因为看起来我单打独斗,我会将我的最终结论作为我自己的答案发布,希望能帮助其他想要做类似事情的人。

我再次更新了proof of concept project。现在,一旦满足所有异步依赖项,新的单一复合依赖项就是新重命名的@Produced的实际@Module 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通过这种方式,@Inject之后我实际上可以@Produce

不像我想的那么干净,但仍然比没有DI更好。现在可以按任何顺序满足任何数量的异步依赖关系,无论何时都可以满足,并且一旦所有异步依赖关系都准备就绪,就会设置一个Future并准备SessionProvisionComponent来注入与@Produced的依赖关系{ {1}}依赖项。

非常高兴。