前言
在Dagger2神器入门(一)中,我们了解了什么是依赖注入,那么在这一章中,我们将逐渐入门Dagger2。接下来我们会通过demo形式给大家展现Dagger2的神奇之处。
上文中通过”开车上班”的例了解了什么是”依赖注入”,那么我们继续这例子。我们知道车由发动机,轮子,车座等部件组成。那么,如果我们要造一辆车的话,可能需要这些部件。回归到代码中,我们new一个Car可能需要发动机,轮子,车座等对象。
原始依赖
首先,我们创建造车所需要的部件。
发动机
/** * 发动机 */ public class Engine { public Engine(){ Log.d(Config.TAG,"new Engine()"); } }
车座
/** * 车座 */ public class Seat { public Seat(){ Log.d(Config.TAG,"new Seat()"); } }
轮子
/** * 轮子 */ public class Wheel { public Wheel(){ Log.d(Config.TAG,"new Wheel()"); } }
上面3个类用到了Config配置类,其实就是一个字符串。
public class Config { public static final String TAG = "TAG"; }
另话:把公共的部分抽取出来,也是代码规范的一部分。在今后的工作中,需要不断review自身代码,随着技术水平的提高,代码质量也需要不断提高。
上面的代码中,我们写了3个类,都是用来造车的构件。那么对于造车,对应于我们的代码就是new Car(),就是这么简单。但是Car可能需要Engine,Seat,Wheel 等组件。那么我们来造个车试试。
public class Car { private Engine engine; private Seat seat; private Wheel wheel; public Car() { engine = new Engine(); seat = new Seat(); wheel = new Wheel(); Log.d(Config.TAG, "new Car()"); } }
按照正常逻辑,Car类应该是这样写。那么我们在new Car()试试。
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Engine() 06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Seat() 06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Wheel() 06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Car()
就这样,我们把Car给new出来了,这样写也是没有问题的。
那么接下来我们用Dagger2的方式,来做做试试,先不管他们之间的区别,just do it。做出来效果之后再回过头来反思。
Dagger2依赖注入
下面让我们一步一步走下去:
1 在modle的build.gradle文件中添加
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' compile 'com.google.dagger:dagger:2.0.2' provided 'org.glassfish:javax.annotation:10.0-b28'
2 写一个Module类,管理上面的三个依赖。
@Module public class CarModule { @Provides public Engine provideEngine(){ return new Engine(); } @Provides public Seat provideSeat(){ return new Seat(); } @Provides public Wheel provideWheel(){ return new Wheel(); } }
3 写一个Component类,来连接Module和你的Car。
@Component(modules = CarModule.class) public interface CarComponent { void inject(Car car); }
4 重写Car类
public class Car { @Inject Engine engine; @Inject Seat seat; @Inject Wheel wheel; // private Engine engine; // private Seat seat; // private Wheel wheel; public Car() { // engine = new Engine(); // seat = new Seat(); // wheel = new Wheel(); DaggerCarComponent .builder() .carModule(new CarModule()) .build() .inject(this); Log.d(Config.TAG, "new Car()"); } }
看看输出
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Engine() 06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Seat() 06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Wheel() 06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Car()
是不是达到了和之前一样的效果呢?是不是从第3步开始,就不知道为什么这样写了呢?
分析
我们看看CarModule类是用一个@Module注解的类,里面的方法是使用@Provides注解。什么意思呢?
@Moudle 表示该类能够管理并提供依赖;你需要造车,但是车依赖于发动机,轮胎以及车座,那么写一个@Module注解的类来帮你管理这些依赖。
@Provides 表示该方法提供依赖;通过这个注解的方法,能给你提供依赖,看代码应该清楚。
我们知道了管理并提供依赖的类,那么我们就可以通过它来直接使用依赖。但是Dagger2为了解耦,提供了一个中介,@Component注解,也就是我们的第4步。
@Component(modules = CarModule.class) public interface CarComponent { void inject(Car car); }
我们要清楚,@Component就