Dagger2的使用

    关于依赖注入(控制反转)请参考http://blog.csdn.net/beakin2000/article/details/9039743
    本文参考了http://code.tutsplus.com/tutorials/dependency-injection-with-dagger-2-on-android--cms-23345

1.配置build.gradle。
在用Android Studio创建好一个应用后,配置build.gradle,其中项目中的build.gradle如下所示:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

配置app下的build.gradle,如下所示:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.cj.j.dagger"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.google.dagger:dagger:2.0'
    apt 'com.google.dagger:dagger-compiler:2.0'
    provided 'org.glassfish:javax.annotation:10.0-b28'
}
    接着点击下图所示按钮(或者Tools -> Android -> Sync Project with Gradle Files)
![这里写图片描述](https://img-blog.csdn.net/20151229114318046)

2.创建依赖对象:Motor类与Vehicle类
    接下来创建两个类:Motor与Vehicle。其中Vehicle类依赖Motor类。Motor类如下所示:
public class Motor {
    private int rpm;
    public Motor(){
        this.rpm = 0;
    }

    public int getRpm() {
        return rpm;
    }

    public void accelerate(int value){
        rpm = rpm + value;
    }

    public void brake(){
        rpm = 0;
    }
}
Vehicle类如下:
public class Vehicle {
    private Motor motor;

    public Vehicle(Motor motor){
        this.motor = motor;
    }

    public void increaseSpeed(int value){
        motor.accelerate(value);
    }

    public void stop(){
        motor.brake();
    }

    public int getSpeed(){
        return motor.getRpm();
    }


}

3.创建Module类
接着来创建Module类,如下

@Module
public class VehicleModule {
private Motor motor = new Motor();
    @Provides @Singleton
    Motor provideMotor(){
        return motor;
    }

    @Provides @Singleton
    Vehicle provideVehicle(){
        return new Vehicle(motor);
    }
}

注:Module类必须要添加@Module注释。在提供实例的方法前添加@Provides和@Singleton。在后面的MainActivity类中,我们需要提供Motor类与Vehicle类的实例,这也是为什么这里要创建两个Provider。

4.创建Component类
紧接着创建Component类,如下:
@Singleton
@Component(modules = VehicleModule.class)
public interface VehicleComponent {
void inject(MainActivity activity);
Vehicle provideVehicle();
Motor provideMotor();
}

5.使用Component获取对象。
在使用DaggerVehicleComponent前先编译,编译后apt会生成该类。

public class MainActivity extends AppCompatActivity {

    @Inject Vehicle vehicle;
    @Inject Motor motor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        VehicleComponent component = DaggerVehicleComponent.builder().vehicleModule(new VehicleModule()).build();
        component.inject(this);
        test();
    }

    private void test(){
        vehicle.increaseSpeed(20);
        motor.accelerate(200);
        Toast.makeText(this,String.valueOf(vehicle.getSpeed()),
        Toast.LENGTH_LONG).show();
    }
}

6.原理
通过查看DaggerVehicleComponent类,发现其内部类Builder中维持着一个VehicleModule的变量,当调用build()后便会将当前的buider对象传入DaggerVehicleComponent中并new了一个DaggerVehicleComponent,DaggerVehicleComponent的构造方法里调用了initialize(final Builder builder)方法,完成初始化。
build()方法:

public VehicleComponent build() {  
      if (vehicleModule == null) {
        this.vehicleModule = new VehicleModule();
      }
      return new DaggerVehicleComponent(this);
    }

initialize(final Builder builder)方法:

private void initialize(final Builder builder) {  
    this.provideVehicleProvider = ScopedProvider.create(VehicleModule_ProvideVehicleFactory.create(builder.vehicleModule));
    this.provideMotorProvider = ScopedProvider.create(VehicleModule_ProvideMotorFactory.create(builder.vehicleModule));
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideVehicleProvider, provideMotorProvider);
  }

inject(MainActivity activity)是如何完成实例的注入

当用户在MainActivity中调用component.inject(this)时,通过源码发现DaggerComponent却调用了MainActivity_MembersInjector类injectMembers(MainActivity instance)方法。代码如下:

public void injectMembers(MainActivity instance) {  
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    supertypeInjector.injectMembers(instance);
    instance.vehicle = vehicleProvider.get();
    instance.motor = motorProvider.get();
  }

看到这里就会明白要被注入的变量不能设为private,否则无法初始化。当然调用inject方法必须在对象使用前,不然会报null错误。

vehicleProvider是VehicleModule_ProvideMotorFactory的一个实例,它是根据VehicleModule类中的方法生成的,当调用它的get()方法时,它会调用VehicleModule的provideMotor()方法,也就是我们自己提供的实例。

总结
本质上,Dagger2是根据Module类中我们提供的实例生成一个个工厂(工厂模式),当需要某一个对象的实例时就调用该工厂的get()方法,它通过调用Module中我们自己定义的方法获得相应的对象。而DaggerVehicleComponent则使用了工厂方法设计模式,当你需要注入时,它会通过上述的工厂获得需要被注入的对象,当然它也可以提供我们已提供的实例。通过几行代码就能帮我们实例化一个个对象,使得我们的代码更加精简。很不错!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值