天天看点

用Dagger2在Android中实现依赖注入

依赖注入这个模式(模式已经用烂了,这里再烂一次)是用来给应用的各部分解耦的。使应用开发更加可扩展,更容易维护。通过本文你会学到如何使用Dagger2来处理依赖。

如果以对象需要另外的一个对象才能完成一个完整功能的话,那么这里就存在一个依赖。比如,悟空要用金箍棒才能三打白骨精,要筋斗云才能十万八千里。悟空有对金箍棒和筋斗云的依赖。你可以在悟空对象里初始化金箍棒,也可以用一个工厂方法批量生产金箍棒。使用依赖注入可以无需一个专门的类来初始化这些依赖对象。这样就实现了解耦。

Android Studio是必须的。其他:

注解讲解:

<code>@Module</code>这个annotation修饰的类专门用来提供依赖

<code>@Provides</code>这个annotation修饰的方法用在<code>Module</code>类里

<code>@Inject</code>用来annotation一个依赖(可以是构造方法、field或者一般的方法)

<code>@Component</code>连接<code>@Module</code>和注入的桥梁

这些名词看起来非常抽象。下面稍微解释一下。依赖反射并没有什么神奇的地方。只不过是我们需要单独写初始化依赖的地方由其他的框架代替了。这个依赖关系也有我们常写的代码转移到了“配置文件”中。

在很久以前,依赖注入的框架就是这样处理依赖注入的:读取配置文件的依赖关系,然后用反射的方法初始化被依赖对象并赋值给调用依赖的对象。比如,我们之前在悟空类中初始化金箍棒:

后来有了使用配置文件的依赖注入(这里都是虚构的文件格式):

在悟空使用金箍棒的时候,依赖注入框架自动初始化好了金箍棒,并赋值给了悟空。

现在使用Dagger2。这里就有不得不说的牛X的地方了。因为是在Android里能用的资源没有后端那么多。尤其反射消耗比较大!所以Dagger为了满足移动开发节约资源的需要,没有使用反射实现依赖注入。而是在编译的时候同时生成依赖注入的相关代码。生成代码的根据就是前文中说明的那些注解(annotation)以及使用这些annotation的类、接口。

总结起来就一句话,Dagger把你需要在悟空类里写的金箍棒类的初始化代码都根据注解替你自动生成了!只不过这种生成的代码比明晃晃的使用<code>new</code>初始化的方法更加复杂一些。

把大象装冰箱一共分几步:

定义依赖和被依赖的对象的类,悟空类和金箍棒类。“悟空类”和“金箍棒类”的构造函数用<code>@Inject</code>注解修饰。

创建一个interface,并用<code>@Component</code>注解修饰。一般叫做<code>XXXComponent</code>。里面写一个注入方法:<code>void inject(Wukong wk);</code>。这里<code>Wukong</code>只是一个例子。任何你准备要注入的类都可以代替上面参数的<code>Wukong</code>类。

在需要注入的地方写<code>@Inject</code>的field。

最后,Dagger会根据上面的内容和最后的<code>@Component</code>接口生成一个<code>DaggerXXXComponent</code>的类型,使用这个类型来实现注入。上面的1到3步可以理解为依赖的配置。最后的<code>XXXComponent</code>代替古老的Reflect方式实现注入。

上文提到过多次。Dagger 2厉害的地方就在于这个库完全不用反射,而是用在编译期生成代码的方式实现的依赖注入。这个特点导致在Android Studio配置的时候需要做一些额外的工作。

这里假设你已经创建了一个新的Android应用项目。下面打开<code>build.gradle</code>文件,我们一步一步的来完成Dagger2的配置。

为什么要加一个新的plugin呢?这个是为后面使用的<code>kapt</code>和<code>provided</code>提供支持的。gradle本身不支持这两个操作。

dagger, 我们要用的正主。

dagger-compiler, 用来生成代码。

java.annotation, 提供Dagger意外的注解

最后,同步Gradle。

下面就是Dagger一展身手的时候了。

悟空:

金箍棒:

悟空对金箍棒有依赖,所以金箍棒属性有<code>@Inject</code>注解修饰。

因为两个类都需要Dagger创建,所以在构造函数上都有<code>@Inject</code>注解。

创建<code>@Module</code>注解的类,并在其中添加<code>@Provides</code>注解修饰的方法。这些方法创建被依赖的对象。

<code>@Singleton</code>注解表明,这个被依赖的对象在应用的生命周期里只有一个实例。

这个里的<code>@Provides</code>方法和前一步说到的<code>@Inject</code>注解的构造函数两个可以只写一个。

<code>@Module</code>和<code>@Provides</code>方法提供了被依赖的对象。<code>@Inject</code>在<code>@Component</code>接口出现的地方则是指明了需要注入的地方(一般是一个field)。<code>@Component</code>接口就是用来把他们连接起来的。

其中<code>inject()</code>方法里使用的对象,就是包含<code>@Inject</code>的field的需要注入的对象。

在这个接口中也可以不用<code>inject()</code>方法,而使用<code>provideXXX()</code>方法后面会有更多介绍。

经过前面的步骤,依赖和被依赖对象关系都已经配置好了。下面就来获取被依赖对象来注入依赖对象。

首先主要到属性<code>@Inject Wukong wukong;</code>已经在<code>MainActivity</code>声明了。这里表明一个依赖关系:这个activity依赖于悟空,并准备注入悟空对象。

Dagger2会在编译器自动生成依赖注入的代码,所以在添加上面的代码之前需要编译一下。<code>DaggerXiYouComponent</code>就是Dagger根据我们的<code>XiYouModule</code>类生成的代码。

在这一步给<code>DaggerXiYouComponent</code>的<code>builder</code>添加<code>XiYouModule</code>的实例。如果这个Module只需要用到无参构造函数的话可以用一种省略用法:<code>create()</code>方法。可以简写为:

Component接口的对象调用<code>inject(this)</code>方法之后注入即完成。所以可以直接使用<code>@Inject Wukong wukong;</code>属性来调用方法:<code>welcomeTextView.setText(wukong.useJinGuBang());</code>最后在activity中显示方法返回的文字。

运行代码,看看结果吧。

以上内容可以概括为:什么被依赖,就把什么放在<code>@Module</code>类里(或者什么被依赖,就给什么添加<code>@Inject</code>的无参构造函数)。什么有依赖(<code>@Inject</code>属性),就把什么放在<code>@Component</code>接口的<code>inject()</code>方法参数里。(或者有什么<code>@Inject</code>属性,就在<code>@Component</code>接口里provide什么对象)。这个概括不一定严密,但是基本用法全部包括了。

依赖注入是很有用的。以上的内容只是Dagger2依赖注入的一部分。各位读者还需要根据官方文档多加练习才能更好的理解依赖注入和Dagger的各种用法。

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!

本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/5363301.html,如需转载请自行联系原作者

继续阅读