将基于Guice的项目迁移到Dagger

hko*_*sha 7 java guice dagger-2

我有一个使用香草Guice的Guice项目; 没有Assisted-Inject,没有AOP,没有额外的插件扩展Guice等.要在Android上更轻松地运行它,Dagger似乎是一个更好的解决方案.每个类都有一个依赖项和一个带@Inject注释的构造函数.不使用场或方法注入.

模块非常简单(使Guice成为一种过度杀伤)并且大多包含如下所示的绑定:

class SomethingModule extends AbstractModule {

  protected void configure() {
    Bind(Handler.class)
      .annotatedWith(Names.named("something"))
      .to(SomeImplementation.class);
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

后来使用如下:

Injector inj = Guice.createInjector(new SomethingModule());
... = inj.getInstance(SampleInterface.class);
// and rest of the code.
Run Code Online (Sandbox Code Playgroud)

不幸的是,我无法理解Daggers的术语.您能指导我将Guice模块直接转换/转换为Dagger模块吗?

匕首有:

  • Dagger的组件.
  • Dagger的模块.
  • @Provides
  • @Inject

Guice有:

  • @Inject
  • @Named (或任何自定义注释,如果正确实施).
  • 我们的模块扩展AbstractModule.
  • @Provides 在模块中.
  • Guice Injector是从模块创建的.

这些如何相关?

更新:除了EpicPandaForce的不错答案之外,这些幻灯片也可以提供帮助.

Epi*_*rce 4

Bind(Handler.class)
.annotatedWith(Names.named("something"))
.to(SomeImplementation.class);
Run Code Online (Sandbox Code Playgroud)

将翻译为

@Module
public class SomethingModule {
    @Provides
    @Named("something")
    //scope if needed
    public Handler handler() {
        return new SomeImplementation();
    }
}
Run Code Online (Sandbox Code Playgroud)

这将绑定到“ Injector”(组件):

@Component(modules={SomethingModule.class})
//scope if needed
public interface SomethingComponent {
    @Named("something")
    Handler handler();

    void inject(ThatThingy thatThingy);
}
Run Code Online (Sandbox Code Playgroud)

这是您必须使用 APT 生成的构建器创建的“注入器”:

SomethingComponent somethingComponent = DaggerSomethingComponent.builder()
                                           .somethingModule(new SomethingModule()) //can be omitted, has no params
                                           .build();
somethingComponent.inject(thatThingy);
Run Code Online (Sandbox Code Playgroud)

那东西在哪里

public class ThatThingy {
    @Inject
    @Named("something")
    Handler handler;
}
Run Code Online (Sandbox Code Playgroud)

组件通常存在于每个作用域,因此例如@ApplicationScope一个“注入器”(组件)。范围界定可以通过子组件和组件依赖关系来实现。

重要的事实是,组件具有提供方法(如果使用组件依赖项,则这些方法是继承到子范围组件的依赖项)和void inject(X x);格式化方法。这是每种混凝土类型现场注射所必需的。例如,基类只能注入自身,而不能注入其子类。但是,您可以编写一个名为 的方法protected abstract void injectThis(),该方法也会在子类上调用 .inject(this)

由于我还没有真正使用过 Guice,所以我不确定我是否错过了什么。我想我忘记了构造函数注入,这是一个问题,因为虽然 Dagger 确实支持它,但它无法重新配置。对于重新配置,您必须使用模块,并自己在构造函数中进行注入。

@Module(includes={ThoseModule.class, TheseModule.class})
public abstract class SomethingModule {
    @Binds
    abstract Whatever whatever(WhateverImpl impl);
}

@Singleton
public class WhateverImpl implements Whatever {
    Those those;
    These these;

    @Inject
    public Whatever(Those those, These these) {
        this.those = those;
        this.these = these;
    }
}

@Component(modules={SomethingModule.class})
@Singleton
public interface SomethingComponent {
    These these();
    Those those();
    Whatever whatever();
}
Run Code Online (Sandbox Code Playgroud)

  • 如果 `Y` 有一个 `@Inject` 构造函数,它将被自动调用 (3认同)
  • 挑剔:与“bind(X.class).to(Y.class)”更接近的 Dagger 等效项是“@Provides X ProvideX(Y y) { return y; }` (2认同)