抽象超类中的Generic @Inject’d字段

考虑一组MVP-ish类型。 存在一个抽象的Presenter,带有View接口:

public interface View { //... } public abstract class AbstractPresenter { @Inject V view; //... } 

然后,让我们有一个特定的具体的presenter子类,其视图接口和实现:

 public interface LoginView extends View { //... } public LoginPresenter extends AbstractPresenter { //... } public class LoginViewImpl implements LoginView { //... } 

在Dagger模块中,我们当然会定义一个@Provides方法:

 @Provides LoginView provideLoginView() { return new LoginViewImpl(); } 

在Guice中你可以用同样的方式编写它,或者只是bind(LoginView.class).to(LoginViewImpl.class)

但是,在Dagger(来自Google的v1和2.0-SNAPSHOT)中,这会产生错误,因为在为AbstractPresenter创建绑定接线时,它无法确定V是什么。 另一方面,Guice指出,因为它实际上是在创建一个LoginPresenter ,所以它需要一个LoginView的实现。

匕首1.2.2:

 foo.bar.AbstractPresenter$$InjectAdapter.java:[21,31] cannot find symbol symbol: class V location: class foo.bar.AbstractPresenter$$InjectAdapter 

Dagger 2.0-SNAPSHOT:

 Caused by: java.lang.IllegalArgumentException: V at dagger.internal.codegen.writer.TypeNames$2.defaultAction(TypeNames.java:39) at dagger.internal.codegen.writer.TypeNames$2.defaultAction(TypeNames.java:36) at javax.lang.model.util.SimpleTypeVisitor6.visitTypeVariable(SimpleTypeVisitor6.java:179) at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1052) at dagger.internal.codegen.writer.TypeNames.forTypeMirror(TypeNames.java:36) at dagger.internal.codegen.MembersInjectorGenerator.write(MembersInjectorGenerator.java:142) at dagger.internal.codegen.MembersInjectorGenerator.write(MembersInjectorGenerator.java:61) at dagger.internal.codegen.SourceFileGenerator.generate(SourceFileGenerator.java:53) at dagger.internal.codegen.InjectBindingRegistry.generateSourcesForRequiredBindings(InjectBindingRegistry.java:101) at dagger.internal.codegen.ComponentProcessor.process(ComponentProcessor.java:149) 

我的问题:这是一个错误吗? 这是一个缺少的function吗? 或者这是Dagger保护我们的性能问题(GWT RPC中的SerializableTypeOracleBuilder)?

请注意,当V被称为ProviderLazy等时,会出现同样的问题。

这看起来像一个bug,因为它不应该抛出exception,但它应该记录一个警告,解释类型参数需要绑定到特定类型。

其余的是Dagger2,我正在使用2.1-SNAPSHOT。 您没有提供将执行注入的示例@Component ,如果没有它,Dagger2 2.1-SNAPSHOT实际上不会报告问题。 它可能已经修复了你的问题而且我看到了一个稍微不同的版本,但如果没有,那么我认为你的组件看起来像这样:

 @Component public interface PresenterComponent {  void inject(AbstractPresenter presenter); } 

当Dagger2处理它时,它无法确定V的具体类型,因此它不知道要插入什么类型。 它不能只插入说LoginView因为如果传递了AbstractPresenter它会破坏。

但是,如果您使用以下说法,那么Dagger2可以确定它需要将LoginView注入AbstractPresenter并安全地执行此操作。

 @Module public class LoginModule { @Provides LoginView provideLoginView() { return new LoginViewImpl(); } } @Component(modules = LoginModule.class) public interface LoginComponent { void inject(LoginPresenter presenter); } 

除非您无法控制何时创建对象,例如,如果某个框架为您创建它然后传入以供初始化,那么如果可以的话,在构造函数上使用@Inject要好得多,例如:

 public LoginPresenter extends AbstractPresenter { //... @Inject LoginPresenter(LoginView view) { super(view); //... } } 

这是因为Type参数。 当你有一个类型参数时,注入不起作用。 你需要做这样的事情,

 bind(new LoginPresenter(){});