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

How to implement Dependency Injection using Dagger2 on the given scenario? (Manage injection hierarchy on Dagger2)

补充ose 我有以下 类:

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 实现依赖注入的正确方法是什么?


我的方法...

到目前为止,我处理这种 os 场景的方式是:

配置

@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);
    }    
}

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

如果您将 Bar 的构造函数的签名更改为以下内容,您应该会达到您想要的效果(构造函数注入)。

class Bar {
    Foo foo;

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

那么你只需要在provider中指定Bar的依赖,写成方法参数就可以了,像这样:

@Provides Bar provideBar(Foo foo)

由于FooBar通过@Provide方法已知dagger,dagger会自动创建一个Foo的实例来获取[=12的实例=].像这样的构造函数注入将具有使您的代码易于进行单元测试的额外优势。在您的测试中,您可以将真实的 Foo 换成模拟的 Foo 并测试 FooBar.

上的交互

属性 注入只有在您无法访问构造函数时才是最好的(比如 Android ActivityService)。对于您的其他依赖项,最好使用构造函数注入。

您不需要使用模块来提供纯 classes。您可以直接注释 classes。要始终将 Foo 作为单例提供,您可以注释 class 本身。

@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;
  }
}

当您需要 build/configure 实例或提供接口的实现时,需要模块。例如:

@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);
}