What is dragger2?
dragger是一个依赖注入框架,不同于传统的依赖注入框架的是,dragger的代码是使用代码生成器进行机器生成,区别于传统的DI框架依赖反射。所以,dragger2更适合于android开发。并且,dragger2是基于JSR330,通过@Inject注解标示依赖,这个注解可用于方法(method),域(field),构造函数(ctor)。
我们可以先看一下dragger2中的注解:
Module是用来注解依赖注入上下文(dependency injection context),该类定义了一系列用于注解的对象集合。而这个类中的方法如果返回依赖的对象,那么就应该使用@Provides进行注解。如果你希望返回的对象应该是个实体类(单例的),那么可以和@Singletion进行注解,那么只会返回同一个实例。
我们可以看到@Inject定义了需要DI的地方,而Modlue则是对象的提供者,那么到这里,我们必定需要一种机制作为桥梁,来连接二者,这就是@Component的作用,@Component是用于interface的注解,这个接口会被Dragger2用来生成代码,通常生成的代码都是有固定的范式的,比如,在这个接口名之前加一个Dragger作为前缀。这个生成的代码有一个create方法,它被用于配置对象(我们稍后会看到)
HOW TO USE:
对于Android Studio 需要在工程的gradle中添加如下代码
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加apt命令 } } allprojects { repositories { jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 用于添加apt命令 然后切换到app的gradle中
代码如下:
apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.chan.daggerdemo" minSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' apt 'com.google.dagger:dagger-compiler:2.0.2' //指定注解处理器 compile 'com.google.dagger:dagger:2.0.2' //dagger公用api provided 'org.glassfish:javax.annotation:10.0-b28' //添加android缺失的部分javax注解 }
package com.vogella.android.dagger2simple; public class NetworkApi { public boolean validateUser(String username, String password) { // imagine an actual network call here // for demo purpose return false in "real" life if (username == null || username.length() == 0) { return false; } else { return true; } } }
对于NetworkApi我们需要一个Moudle来生产它的对象:
package com.vogella.android.dagger2simple.modules; import com.vogella.android.dagger2simple.NetworkApi; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; @Module public class NetworkApiModule { @Provides @Singleton public NetworkApi getNetwork(){ return new NetworkApi(); } }
package com.vogella.android.dagger2simple.components; import android.app.Activity; import com.vogella.android.dagger2simple.MainActivity; import com.vogella.android.dagger2simple.NetworkApi; import com.vogella.android.dagger2simple.modules.NetworkApiModule; import javax.inject.Singleton; import dagger.Component; @Singleton @Component(modules = {NetworkApiModule.class}) public interface DiComponent { // to update the fields in your activities void inject(MainActivity activity); }
package com.vogella.android.dagger2simple; import android.app.Application; import com.vogella.android.dagger2simple.components.DaggerDiComponent; import com.vogella.android.dagger2simple.components.DiComponent; public class MyApplication extends Application { DiComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerDiComponent.builder().build(); } public DiComponent getComponent() { return component; } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.vogella.android.dagger2simple" > <application android:name="MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>我们可以看到DiComponent接口,它有一个inject方法,该方法的参数就是需要DI的类,你可以把它想象成容器,而Moudle是产生对象的,这些对象通过Component注入到容器当中,所以你可以看到:
package com.vogella.android.dagger2simple; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; import javax.inject.Inject; public class MainActivity extends Activity { @Inject NetworkApi networkApi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((MyApplication) getApplication()).getComponent().inject(this); boolean injected = networkApi == null ? false : true; TextView userAvailable = (TextView) findViewById(R.id.target); userAvailable.setText("Dependency injection worked: " + String.valueOf(injected)); } }
结果: