Dagger版本:2.16

Dagger 2.10版本引入的dagger-android是一个专为Android设计的除了Dagger主模块和dagger-compiler之外的全新的模块,本文中,我们将介绍使用dagger-android的方法步骤,当然,前提是你要具备相关的Dagger知识。

本文主要介绍Activity的注入,但是也可以作为其他Android组件注入的参考

Dagger常用配置

在Android端的Dagger的常用配置包含包含Application Component 以及Application Module,前者是用来注入Activity,Fragment等Android组件。

Application Component 代码

@Component(modules = { AppModule.class })

interface AppComponent {

@Component.Builder

interface Builder {

@BindsInstance Builder application(App application);

AppComponent build();

}

void inject(FeatureActivity featureActivity);

}

Application Module 代码

@Module

abstract class AppModule {

@Provides

static Context provideContext(App application) {

return application.getApplicationContext();

}

@Singleton

@Provides

static SomeClientApi provideSomeClientApi() {

return new SomeClientApiImpl();

}

}

App的Application 代码

@Module

abstract class AppModule {

@Provides

static Context provideContext(App application) {

return application.getApplicationContext();

}

@Singleton

@Provides

static SomeClientApi provideSomeClientApi() {

return new SomeClientApiImpl();

}

}

因为Android框架已经将这些组件实例化,所以我们必须执行成员注入,使用 @Inject注解对可见类进行标注,如下:

public class FeatureActivity extends AppCompatActivity {

@Inject SomeClientApi mSomeClientApi;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

((App)getApplication())

.getAppComponent()

.inject(this);

}

}

然而,这种方式破坏了依赖注入的核心准则:一个类不应该知道它是如何被注入的,最新引入的dagger-android模块就是为了解决这个问题——将注入类与注入器分离开来。

使用新的dagger-android模块

首先,将以下Gradle的依赖添加到你的build.gradle文件中:

// Dagger core dependencies

annotationProcessor 'com.google.dagger:dagger-compiler:2.16'

implementation 'com.google.dagger:dagger:2.16'

// Dagger Android dependencies

annotationProcessor 'com.google.dagger:dagger-android-processor:2.16'

implementation 'com.google.dagger:dagger-android:2.16'

implementation 'com.google.dagger:dagger-android-support:2.16'

在我们的项目中,新模块的配置需要不止一个component和module。每一个Activity都需要自己的subComponent并将其与Application的Component连接起来。以下是我建议的类结构:

/

| App (extending Application)

| AppComponent

| AppModule

| ContributeAndroidInjectorsModule // 3

+ feature/

| FeatureModule // 2

| FeatureActivityModule // 1

| FeatureActivity

正如我们所见,在上文中所提到的典型配置之外额外增加了三个类。每一个feature拥有它自己的component以及module。

注:我使用术语“feature”来描述一个app中的显示界面(或者说一个Activity)。

1.FeatureActivityModule

正如前文提到的,每一个Activity现在需要它自己的subcomponent,为此,Dagger引入了一个非常方便的注解来供我们使用以提醒Dagger生成subcomponent的代码。就像这样:

@Module

public abstract class FeatureActivityModule {

@ActivityScope

@ContributesAndroidInjector(modules = { FeatureModule.class })

abstract FeatureActivity contributeFeatureActivityInjector();

}

2.FeatureModule

我们将Activity自身需要的绑配置在这个module中。此module中的绑定仅仅在此Activity和它的subcomponent中有效,除非该module在其他component中使用。假设我们正在使用MVP的设计模式,一下是你通常用来绑定View的方式:

@Module

abstract class FeatureModule {

@ActivityScope

@Binds

abstract FeatureView provideFeatureView(FeatureActivity featureActivity);

}

3.ContributeActivityModule

到目前为止,我们告诉了Dagger为我们的Activity生成subcomponent,但是我们并没有将subcomponent与Applicaiton的Component连接起来。为了实现这个,我们需要另一个module来持有所有Activity的module。这个module将会被包含在Application的Component中。

@Module(includes = {

FeatureActivityModule.class

// Other Activity modules will be added here

})

abstract class ContributeActivityModule {

}

4.AppComponent

Applicaiton的Component配置(使用Kotlin)

我更喜欢使用Java来写Dagger的module,因为Kotlin缺少static修饰符,所以当我们使用companion object时需要在同一个类中增加额外的@Module注解,这是我不太喜欢的。

@Singleton

@Component(modules = [

AndroidSupportInjectionModule::class, // 1

ContributeActivityModule::class, // 2

AppModule::class

])

interface AppComponent : AndroidInjector { // 3

@Component.Builder

abstract class Builder : AndroidInjector.Builder() // 4

}

(译者注:Java代码如下)

@Singleton

@Component(modules = [

AndroidSupportInjectionModule::class, // 1

ContributeActivityModule::class, // 2

AppModule::class

])

public interface AppComponent extends AndroidInjector { // 3

@Component.Builder

abstract class Builder extends AndroidInjector.Builder {

}

}

注意:AppComponent中的一些修改:

为了使Dagger Android能够正常运行,我们在Application的Component中包含了AndroidSupportInjectionModule

包含ContributeActivityModule是为了将Activity的subcomponent与AppComponent连接起来

AppComponent必须继承自AndroidInjector 并将其泛型设定为Application类

Appcomponent的Builder可以选择性的继承AndroidInjector.Builder并提供Application类。因为这个base类已经实现了公共的component builder,这个builder中包含了一个设置Application实例的方法以及另一个构建component的方法,这可以很轻松的为我们介绍一些代码行数。

5.然后我们修改我们的App文件,使其继承DaggerApplication并实现基本方法,代码如下

class App : DaggerApplication() {

private val appComponent: AndroidInjector by lazy {

DaggerAppComponent

.builder()

.create(this)

}

override fun applicationInjector(): AndroidInjector {

return appComponent

}

}

(译者注:Java代码如下)

public class App extends DaggerApplication {

private AppComponent appCompoent;

@Override

public void onCreate() {

appCompoent = DaggerAppComponent.builder()

.application(this)

.build();

super.onCreate();

}

@Override

protected AndroidInjector extends DaggerApplication> applicationInjector() {

return appCompoent;

}

}

6.最后,在FeatureActivity中,我们将之前写的注入Activity的代码删除,同时使其继承自DaggerAppCompatActivity而不是AppCompatActivity

class FeatureActivity : DaggerAppCompatActivity(), FeatureView {

@Inject

internal lateinit var presenter: FeaturePresenter

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.feature_activity)

}

}

(译者注:Java代码如下)

public class FeatureActivity extends DaggerAppCompatActivity implements FeatureView {

public static final String EXTRA_SOME_ID = "some_id";

@Inject FeaturePresenter presenter;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.feature_activity);

}

}

向Acivity的Component中注入自定义参数

在某些场景下你希望注入某些由Activity自己提供的参数。之前常用的方法是在调用Activity的component的inject()法法之前,将参数传递给module的构造函数。例如,如果我们遵循MVP的设计模式,我们饿Presenter将会把View作为其构造参数的一部分,这意味着我们需要将Activity作为一个参数传递给module的构造函数。在使用dagger-android之前,写法是这样:

@Module

class FeatureModule {

private FeatureView view;

public FeatureModule(FeatureView view) {

this.view = view;

}

@Provides FeatureView provideView() {

return view;

}

}

同时,在Presenter中我们会使用构造函数注入:

class FeaturePresenter {

private final FeatureView view;

@Inject

Presenter(FeatureView view) {

this.view = view;

}

public void doSomething() {

}

}

最后,构建Component,传入一个mudle的新实例,并注入Activity:

class FeaturePresenter {

private final FeatureView view;

@Inject

Presenter(FeatureView view) {

this.view = view;

}

public void doSomething() {

}

}

但是,我们如何使用新的dagger-android模块来实现这个呢?毕竟,我们不再需要手动注入Activity,因此无法像以前那样接触到module的创建。

答案是,我们不再需要这样做了。使用dagger-android模块,Activity已经是图表的一部分了。这到底是什么意思呢?你应该可以记得,我们在FeatureModule做了一下配置,用于在任何使用FeatureView的地方,绑定使用FeatureActivity:

@Module

public abstract class FeatureModule {

@Binds

abstract FeatureView provideFeatureView(FeatureActivity featureActivity);

}

}

但是,假如我们想通过接受Activity的Intent向Presenter传递参数呢?假设你通过Activity的Intent的extra传递了一个唯一的ID,并且Presenter需要这个ID,例如,Presenter需要这个ID来进行HTTP请求,实现这个的方式就是使用@Named 注解作为限定符,因此我们的Presenter的代码如下:

class FeaturePresenter {

private FeatureView featureView;

private String someId;

@Inject

public FeaturePresenter(FeatureView featureView, @Named("someId") String someId) {

this.featureView = featureView;

this.someId = someId;

}

public void foo() {

featureView.showFoo();

}

}

答案是非常简单的,我们给FretureModule增加了一个Provides方法,它将会持有一个FeatureActivity的实例,并从intent的extras中获取我们需要的信息:

@Module

abstract class FeatureModule {

@ActivityScope

@Binds

abstract FeatureView provideFeatureView(FeatureActivity featureActivity);

@ActivityScope

@Provides

@Named("someId")

static String provideSomeId(FeatureActivity featureActivity) {

return featureActivity.getIntent().getStringExtra(FeatureActivity.EXTRA_SOME_ID);

}

}

如前所述,这因为FeatureActivity已经在图标中,所以这种实现成为可能。

除了Activity之外的注入

如本文开头所提到的,Fragment注入和其他Android组件都不在本文的范围之内。官方文档介绍了注入Fragment对象,我强烈建议您阅读它。还有更多关于Services、Receivers 和ContentProviders的信息。

总结

Dagger-android模块非常接近Android的依赖注入。如果你正在开发一个新的项目并且准备使用Dagger,你一定要使用Dagger-Android的配置。

官方的示例对我来说太简单了,所以你可以看看我自己的Demo。

dagger android,Dagger-Android使用手册相关推荐

  1. android dagger2 懒加载,Android Dagger依赖注入框架浅析

    今天接触了Dagger这套android的依赖注入框架(DI框架),感觉跟Spring 的IOC差不多吧.这个框架它的好处是它没有采用反射技术(Spring是用反射的),而是用预编译技术,因为基于反射 ...

  2. Android 渗透测试学习手册 翻译完成!

    Android 渗透测试学习手册 中文版 原书:Learning Pentesting for Android Devices 译者:飞龙 在线阅读 PDF格式 EPUB格式 MOBI格式 代码仓库 ...

  3. android 机顶盒 页面布局,Android机顶盒用户DIY手册.doc

    (完美WORD文档DOC格式,可在线免费浏览全文和下载)值得下载! Huawei Technologies Co.,Ltd.Android机顶盒用户DIY手册[键入文档副标题][刘勋][2011-12 ...

  4. Android Tips - 填坑手册

    转载自汤奇V分享的Android-Tips 学习 Android 至今,大大小小的坑没少踩,庆幸的是,在强大的搜索引擎与无私奉献的人们的帮助下,我遇到的坑都顺利地被填平了. 为了便于日后遇到同样的问题 ...

  5. 万普平台Android版SDK开发者手册

    万普平台Android版SDK开发者手册 (标准版Ver1.8.4) 平台简介 万普世纪移动营销服务平台(以下称为"万普平台")的Android 版SDK 提供了一套现成的开发包及 ...

  6. Android 渗透测试学习手册 第三章 Android 应用的逆向和审计

    第三章 Android 应用的逆向和审计 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 在本章中,我们将查看 Android 应用程序或.apk文件,并了解其不同的 ...

  7. Android 渗透测试学习手册 第七章 不太知名的 Android 漏洞

    第七章 不太知名的 Android 漏洞 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 在本章中,我们将了解一些不太知名的 Android 攻击向量,这在 Andr ...

  8. 【Android】Android开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...

  9. android之android.intent.category.DEFAULT的用途和使用

    1.要弄清楚这个问题,首先需要弄明白什么是implicit(隐藏) intent什么是explicit(明确) intent. Explicit Intent明确的指定了要启动的Acitivity , ...

  10. android:layout_with=,android – 难以理解layout_alignWithParentIfMissing

    这仅适用于使用RelativeLayout时. 如果您将元素设置为一个其他元素,则表示该元素位于该元素的左侧. 但是如果这个元素会丢失,因为你删除它,例如它将与父对齐. 举个例子 android:la ...

最新文章

  1. html5 head 标签
  2. resnet50加入fpn_FPN+SSD同时兼顾速度和精度的检测器(二)
  3. 在cygwin下编译c语言
  4. Asterisk 可加载模块
  5. c++ 构造函数数组_“动态数组”的设计与实现
  6. 织梦php gbk转换utf8,dedecms 5.1 utf-8版本英文怎么修改
  7. MongoDB 基础操作
  8. Struts到JSF/Tapestry
  9. Android客户端实现session会话过期的功能
  10. 服务器,Linux,centos7成功安装显卡驱动(超详细)
  11. 解决photoshop cc在4K分辨率下字体过小。
  12. windows memcached php扩展,Memcached 的学习:windows下php开memcached扩展
  13. (34)[NIPS15] Teaching Machines to Read and Comprehend
  14. App Store审核规则简要汇总
  15. 《CSS实战案例汇总》涟漪
  16. 元宇宙虚拟人物风格形象应用场景制作
  17. Kitty代码生成器
  18. Unipus读写课程做题工具
  19. 微信又更新了,这次新增了一个大家喜闻乐见的新功能?
  20. Paging内部原理

热门文章

  1. 揭秘ScheduledThreadPoolExecutor 中ScheduleAtFixedRate迷惑行为
  2. Wifi直连(p2p)一对多音频传输
  3. 聚丙烯(PP)的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  4. 数据仓库系列(19):数据安全
  5. roku能不能安装软件_最佳儿童免费Roku频道
  6. 推荐 10 个不错的网络监视工具,建议收藏!
  7. Html+Css+Js表单验证(正则表达式)
  8. 集成显卡常见故障大全
  9. 没有NVIDIA显卡的情况
  10. Matlab中mat2cell函数使用