我正在尝试将Dagger依赖注入实现到我的应用程序中,但我很难理解它是如何工作的,特别是来自Spring,其中DI更容易,更具声明性.
我想要做的是拥有一堆可以在我的应用程序中使用的注入就绪对象,即SharedPreferences,Network对象(OkHttp,Retrofit,Picasso ...),以及RxJava的EventBus和SchedulerProvider对象.
这个样本似乎提供了我需要的一切,但我无法掌握一些概念.
在上一页中引用的另一个示例中,他们创建了一个使用NetModule中提供的Retrofit对象的GithubService.为此,他们创建了一个像这样的GithubComponent:
@UserScope
@Component(dependencies = NetComponent.class, modules = GitHubModule.class)
public interface GitHubComponent {
void inject(MainActivity activity);
}
Run Code Online (Sandbox Code Playgroud)
他们使用UserScope注释定义自己的范围.既然不能使用@Singleton,这是否意味着该对象不会是Singleton?范围如何真正影响DI?似乎他们只宣布一个命名范围没有更多的影响,但我不确定.
此外,我的应用程序是使用活动与碎片建立的.我是否必须为我的应用中的每个片段创建一个组件?即我需要在整个应用程序中使用我的REST api服务,我是否必须使用它们为每个屏幕声明一个组件?这增加了所需的样板代码量,因此听起来不是很干净.
组件应该是"大型DI提供商",为特定范围提供一切.
例如,您可以拥有一个SingletonComponentwith @Singletonscope,其中添加了每个模块,其中至少有一个@Singleton作用域提供者方法.
@Singleton
@Component(modules={NetworkingModule.class, DatabaseModule.class, MapperModule.class, UtilsModule.class})
public interface SingletonComponent {
// provision methods
OkHttpClient okHttpClient();
RealmHolder realmHolder();
// etc.
}
Run Code Online (Sandbox Code Playgroud)
您可以为每个模块定义配置方法.
public interface DatabaseComponent {
RealmHolder realmHolder();
}
public interface NetworkingComponent{
OkHttpClient okHttpClient();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下你会有
@Singleton
@Component(modules={NetworkingModule.class, DatabaseModule.class, MapperModule.class, UtilsModule.class})
public interface SingletonComponent
extends NetworkingComponent, DatabaseComponent, MapperComponent, UtilsComponent {
// provision methods inherited
}
Run Code Online (Sandbox Code Playgroud)
在模块中,您可以指定工厂方法("提供程序方法"),该方法指定如何创建特定类型的依赖项.
例如,
@Module
public class NetworkingModule {
@Provides
@Singleton
OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()./*...*/.build();
}
@Provides
@Singleton
Retrofit retrofit(OkHttpClient okHttpClient) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将@Singleton范围想象为Spring将为您提供的大型DI容器.
您还可以使用带@Inject注释的构造函数提供类的实例.这可以从组件中接收任何类,该类能够从该范围组件的模块中的提供者方法实例化它(当然还有未组装的依赖项).
@Singleton
public class MyMapper {
@Inject
public MyMapper(RealmHolder realmHolder, OkHttpClient okHttpClient) { // totally random constructor for demo
}
}
Run Code Online (Sandbox Code Playgroud)
要么
@Singleton
public class MyMapper {
@Inject
RealmHolder realmHolder;
@Inject
OkHttpClient okHttpClient;
@Inject
public MyMapper() {
}
}
Run Code Online (Sandbox Code Playgroud)
然后,这将在组件中可用,您甚至可以为它提供配置方法,使其在组件依赖项中可继承:
@Singleton
@Component(modules={...})
public interface SingletonComponent {
MyMapper myMapper();
}
Run Code Online (Sandbox Code Playgroud)
使用Dagger2,您还可以另外创建"子范围组件",继承从给定范围的组件提供的所有依赖项.
例如,您可以继承所有@Singleton作用域组件,但是仍然可以为该新作用域添加新的作用域依赖项,例如@ActivityScope.
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用子组件或组件依赖项创建子范围组件.
.
@ActivityScope
@Subcomponent(modules={MainActivityModule.class})
public interface MainActivityComponent {
MainPresenter mainPresenter();
}
Run Code Online (Sandbox Code Playgroud)
然后可以在其父作用域组件中创建它:
@Singleton
@Component(modules={...})
public interface SingletonComponent {
MainActivityComponent mainActivityComponent(MainActivityModule module);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用单例组件来实例化它:
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
MainActivityComponent mainActivityComponent = singletonComponent.mainActivityComponent(new MainActivityModule(mainActivityHolder));
Run Code Online (Sandbox Code Playgroud)
.
@ActivityScope
@Component(dependencies={SingletonComponent.class}, modules={MainActivityModule.class})
public interface MainActivityComponent extends SingletonComponent {
MainPresenter mainPresenter();
}
Run Code Online (Sandbox Code Playgroud)
为此,您必须在超组件组件中指定提供方法.
然后你可以这样实例化:
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.singletonComponent(singletonComponent)
.mainActivityModule(new MainActivityModule(mainActivityHolder))
.build();
Run Code Online (Sandbox Code Playgroud)
因此,在Dagger2中,您可以通过以下方式获取依赖关系:
@Inject 带注释的构造函数参数@Inject具有带@Inject注释的构造函数的类上带注释的字段@Component提供方法@Inject注释的构造函数创建的类)手动现场注入可能发生在MainActivity您自己不创建的类上.
手动场注入仅注入您正在注入的特定类.基类没有自动注入,他们需要调用.inject(this)组件.
它的工作原理如下:
@ActivityScope
@Subcomponent(modules={MainActivityModule.class})
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.singletonComponent(getSingletonComponent())
.mainActivityModule(new MainActivityModule(this))
.build(); // ensure activity `holder` instead, and retain component in retained fragment or `non-configuration instance`
mainActivityComponent.inject(this);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
992 次 |
| 最近记录: |