匕首:上课不能与钥匙绑在一起

时间:2015-02-27 18:37:55

标签: java android dagger

我正在尝试第一次使用匕首,在配置模块后,我收到一个我不明白的错误。

我的代码是:

public class Parrot {

    private Language language;

    @Inject
    public Parrot(Language language) {
        this.language = language;
    }

    public void sayHello() {
        System.out.println(language.getSalute());
    }
}

public interface Language {
    public String getSalute();
}

public class EnglishLanguage implements Language {

    @Override
    public String getSalute() {
        return "Hello!";
    }
}

我的模块是

@Module(
        injects = Language.class
)
public class PetShopModule {

    @Provides Parrot provideParrot(Parrot parrot){
        return parrot;
    }
}

在代码中我用这种方式

EnglishLanguage lang=SystemApp.getSystemLanguage();
ObjectGraph objectGraph = ObjectGraph.create(new PetShopModule());
objectGraph.inject(myLanguage);
Parrot parrot = objectGraph.get(Parrot.class);

编译器抱怨:

error: com.example.petshop.Language could not be bound 
with key com.example.petshop.Language required by com.example.petshop.PetShopModule 
for com.example.petshop.PetShopModule

我做错了什么?

注意:这只是一个简化的例子,在真正的代码中,EnglishLanguage是一个系统类,我不能修改也不能创建它,只是得到一个参考

2 个答案:

答案 0 :(得分:13)

不要评论你做错了什么,让我们给出正确的例子,并解释那里发生的事情。

这段代码非常完美,保持原样:

public class Parrot {

    private Language language;

    @Inject
    public Parrot(Language language) {
        this.language = language;
    }

    public void sayHello() {
        System.out.println(language.getSalute());
    }
}

public interface Language {
    public String getSalute();
}

public class EnglishLanguage implements Language {

    @Override
    public String getSalute() {
        return "Hello!";
    }
}

使用@Inject构造函数上的Parrot注释,您告诉Dagger,“每当我请求Parrot的实例时,请使用此构造函数来实例化它。”

Dagger发现Parrot需要Language接口的实例,并试图找到一种方法来检索它。但是,由于Language是一个界面,Dagger需要知道要使用哪种具体类型。

由于您无法编辑EnglishLanguage课程,因此您需要为其编写@Provider方法:

@Module
public class PetshopModule {

  @Provides
  Language provideLanguage() {
    return SystemApp.getSystemLanguage();
  }
}

现在,您应该可以从Parrot中获取ObjectGraph的实例,如下所示:

ObjectGraph graph = ObjectGraph.create(new PetshopModule());
Parrot parrot = graph.get(Parrot.class);

我没有对此进行测试,这应该可行。


如果您 能够修改EnglishLanguage课程,则可以执行以下操作。使用EnglishLanguage@Inject构造函数添加注释,并在EnglishLanguage提供程序方法中请求Language实例:

public class EnglishLanguage implements Language {

  @Inject
  public EnglishLanguage() {
  }

  @Override
  public String getSalute() {
    return "Hello!";
  }
}

@Module
public class PetshopModule {

  @Provides
  Language provideLanguage(EnglishLanguage language) {
    return language;
  }
}

在这种情况下,Dagger会查找Language提供程序方法,并实例化EnglishLanguage以返回。

答案 1 :(得分:0)

现有的答案是完美的,但并不能解决我晦涩的情况。

如果您有一个带有两个DI帮助程序类的基本Activity,请确保对它进行扩展的Activity这样做正确!

基本活动类

  private fun initializeObjectGraph() {
    activityObjectGraph = (application as App).getObjectGraph()
        .plus(ActivityModule(this))
        .plus(*getAdditionalModulesForObjectGraph())
  }

  protected open fun getAdditionalModulesForObjectGraph() = arrayOf<Any>()

  abstract fun injectDependencies(activityObjectGraph: ObjectGraph): LifecycleReceiver

扩展活动中所需的替代

  override fun injectDependencies(activityObjectGraph: ObjectGraph): LifecycleReceiver {
    activityObjectGraph.plus(MyModule(this)).inject(this)
    return DummyLifecycleReceiver
  }

  override fun getAdditionalModulesForObjectGraph(): Array<Any> = arrayOf(MyModule(this))