如何在给定场景中使用 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)
由于Foo
和Bar
通过@Provide
方法已知dagger,dagger会自动创建一个Foo
的实例来获取[=12的实例=].像这样的构造函数注入将具有使您的代码易于进行单元测试的额外优势。在您的测试中,您可以将真实的 Foo
换成模拟的 Foo
并测试 Foo
在 Bar
.
上的交互
属性 注入只有在您无法访问构造函数时才是最好的(比如 Android Activity
和 Service
)。对于您的其他依赖项,最好使用构造函数注入。
您不需要使用模块来提供纯 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);
}
补充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);
}
}
问题是,根据 Bar
不应该调用 inject
并且有 Foo
作为参数传递。但是,如果我在项目的其他部分需要 Foo
的单例实例怎么办?我应该如何使用 Dagger2 来实现给定的场景?
如果您将 Bar
的构造函数的签名更改为以下内容,您应该会达到您想要的效果(构造函数注入)。
class Bar {
Foo foo;
@Inject
Bar(Foo foo) {
this.foo = foo;
}
}
那么你只需要在provider中指定Bar
的依赖,写成方法参数就可以了,像这样:
@Provides Bar provideBar(Foo foo)
由于Foo
和Bar
通过@Provide
方法已知dagger,dagger会自动创建一个Foo
的实例来获取[=12的实例=].像这样的构造函数注入将具有使您的代码易于进行单元测试的额外优势。在您的测试中,您可以将真实的 Foo
换成模拟的 Foo
并测试 Foo
在 Bar
.
属性 注入只有在您无法访问构造函数时才是最好的(比如 Android Activity
和 Service
)。对于您的其他依赖项,最好使用构造函数注入。
您不需要使用模块来提供纯 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);
}