首先,使用依赖注入可以带来哪些好处?
1、依赖的注入和配置独立于组件之外,注入的对象在一个独立、不耦合的地方初始化,这样在改变注入对象时,我们只需要修改对象的实现方法,而不用大改代码库。
2、依赖可以注入到一个组件中:我们可以注入这些依赖的模拟实现,这样使得测试更加简单。
3、app中的组件不需要知道有关实例创建和生命周期的任何事情,这些由我们的依赖注入框架管理的。
Dagger2的引用
在整个项目的build.gradle中加入:
- dependencies {
// other classpath definitions here
classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’
}- 在app/build.gradle中分别加入:
// add after applying plugin: ‘com.android.application’
apply plugin: ‘com.neenbedankt.android-apt’- dependencies {
// apt command comes from the android-apt plugin
apt ‘com.google.dagger:dagger-compiler:2.2’
compile ‘com.google.dagger:dagger:2.2’
provided ‘javax.annotation:jsr250-api:1.0’
}
需要注意的是provided代表编译时需要的依赖,Dagger的编译器生成依赖关系的代码,并在编译时添加到IDE 的class path中,只参与编译,并不会打包到最终的apk中。apt是由Android-apt插件提供,它并不会添加这些类到class path中,这些类只用于注解解析,应当避免使用这些类。
注解 | 用法 |
---|---|
@Module | Modules类里面的方法专门提供依赖,所以我们定义一个类,用@Module注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的依赖。modules的一个重要特征是它们设计为分区并组合在一起(比如说,在我们的app中可以有多个组成在一起的modules |
@Provide | 在modules中,我们定义的方法是用这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。 |
@Singleton | 当前提供的对象将是单例模式 ,一般配合@Provides一起出现 |
@Component | 用于接口,这个接口被Dagger2用于生成用于模块注入的代码 |
@Inject | 在需要依赖的地方使用这个注解。(你用它告诉Dagger这个 构造方法,成员变量或者函数方法需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。) |
@Scope | Scopes可是非常的有用,Dagger2可以通过自定义注解限定注解作用域。 |
下面是一个视频播放器网络请求的代码来看实际应用:
@Inject和bufferknifer相似不在详解:
- @Component(modules = NetModule.class)
@Singleton
public interface NetComponent {
ApiService getApiService();
OkHttpClient getOkHttp();
Retrofit getRetrofit();
}
Dagger2中很重要的一点就是它会为@Component注解的类生成代码。它会在类的前面添加上Dagger前缀(比如DaggerTwitterApiComponent.java),也就是这个类负责初始化依赖关系(依赖表 dependency graph)中的实例,并为注解了@Inject 的字段执行注入操作
- @Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
//.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
OkHttpClient okhttpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20,TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor)
.build();
return okhttpClient;
}
在modules中,我们定义的方法是用这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。使用@Singleton注解告诉Dagger整个生命周期中只会被初始化一次。
初始化组件(Instantiating the component)
初始化组件操作应当在Application中进行操作,因为这些实例在整个application生命周期中只会被实例化一次。
private static OwspaceApplication instance;
public static OwspaceApplication get(Context context){
return (OwspaceApplication)context.getApplicationContext();
}
private NetComponent netComponent;
@Override
public void onCreate() {
super.onCreate();
instance = this;
initNet();
initDatabase();
}
private void initNet(){
netComponent = DaggerNetComponent.builder()
.netModule(new NetModule())
.build();
}
private void initDatabase(){
}
可以看到的是我们直接使用NetComponent生成的类DaggerNetComponent并且生成的方法appModule和netModule完成了两个对应module的初始化。因为这里我们继承了Application并作出了修改,所以需要在AndroidManifest.xml中作出修改如下
android:allowBackup=”true”
android:name=”.MyApp”
作用域(Scopes)
Scopes可是非常的有用,Dagger2可以通过自定义注解限定注解作用域。@Singleton是被Dagger预先定义的作用域注解( scope annotation )。没有指定作用域的@Provides方法将会在每次注入的时候都创建新的对象。同样的,你也可以定义自己的Scope注解。
- @Scope
public @interface UserScope {
}
源码:视频播放器源码