关于依赖注入(控制反转)请参考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则使用了工厂方法设计模式,当你需要注入时,它会通过上述的工厂获得需要被注入的对象,当然它也可以提供我们已提供的实例。通过几行代码就能帮我们实例化一个个对象,使得我们的代码更加精简。很不错!