如何在给定方案中使用Dagger2实现依赖注入? (在Dagger2上管理注入层次结构)

时间:2016-11-02 13:41:36

标签: android dependency-injection dagger-2 dagger

假设我有以下类:

class Foo {}

class Bar {
    Foo mFoo = new Foo();
}

class MyActivity extends AppCompatActivity {
     Bar mBar = new Bar();    

    @Override
    protected void onCreate (Bundle savedInstance) {
        super(savedInstance);
    }    
}

从上面的代码可以看出,MyActivity依赖于Bar和Bar取决于Foo。使用Dagger2实现依赖注入的正确方法是什么?

我的方法......

到目前为止,我处理这种类型操作系统的方式是:

配置

@Singleton
@Component(
        modules = {
                MainModule.class,
        })
public interface MainComponent {
    void inject(MyActivity myActivity);

    void inject(Bar bar);
}

@Module
class MainModule {
    @Provides
    @Singleton
    Foo provideFoo() {
        return new Foo();
    }

    @Provides
    @Singleton
    Bar provideBar() {
        return new Bar();
    }
}

注塑

class Bar {
    @Inject Foo mFoo;

    Bar() {inject(this);}        
}

class MyActivity extends AppCompatActivity {
    @Inject Bar mBar;

    @Override
    protected void onCreate (Bundle savedInstance) {
        super(savedInstance);
        inject(this);
    }    
}

问题是,根据this回答,它不应该像那样工作,Bar不应该调用inject并且Foo作为参数传递。但是,如果我在项目的其他部分需要Foo的单例实例,该怎么办?我应该如何使用Dagger2来实现给定的场景?

2 个答案:

答案 0 :(得分:1)

如果将Bar的构造函数的签名更改为以下内容,则应达到所需的效果(构造函数注入)。

class Bar {
    Foo foo;

    @Inject
    Bar(Foo foo) {
        this.foo = foo;
    }        
}

然后你只需要在提供者中指定Bar的依赖关系,方法是将其写为方法参数:

@Provides Bar provideBar(Foo foo)

由于已知FooBar掠过@Provide方法,因此dagger会自动创建Foo的实例以获取Bar的实例。像这样的构造函数注入将具有使代码易于单元测试的附加优势。在您的测试中,您可以使用模拟Foo替换真实Foo,并在Foo上测试Bar的互动。

仅当您无权访问构造函数时(例如,在Android ActivityService中),属性注入才是最佳选择。对于其他依赖项,最好使用构造函数注入。

答案 1 :(得分:1)

您不需要使用模块来提供普通类。您可以直接注释类。要始终将Foo作为单例提供,您可以对类本身进行注释。

@Singleton
@Component
public interface MainComponent {
  void inject(MyActivity myActivity);
}

@Singleton
public class Foo {

  @Inject
  public Foo(){}
}

@Singleton
public class Bar {

  private final Foo foo;

  @Inject
  public Bar(final Foo foo){
    this.foo = foo;
  }
}

当您需要构建/配置实例或提供接口实现时,需要模块。例如:

@Module
class MainModule {
  @Singleton
  @Provides
  Gson gson() {
    return new GsonBuilder.create();
  }

  @Singleton
  @Provides
  IBar bar(Bar bar){
    return bar;
  }
}

// You can also provide an interface with the @Binds attribute instead
// of using the traditional @Provides annotation
@Module
abstract class MainBindsModule {
  @Singleton
  @Binds
  abstract IBar bar(Bar bar);
}