在一个项目的开发过程中,像组装一个汽车一样,一个部件一个部件的往上面添加。但是 按照传统的方法这些部件都是通过 在一个new出来的,比如有个httpService 用来网络访问,往往使用方式都是如下
public class MineActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
HttpService httpService = new HttpService();
....
}
}
然而 这种方式 需要在每个 用到这个httpService 的地方都要像上面那样去new
如果有一天这个HttpService 的构造方法 改动了,那么这些每个引用到 new HttpService() 的地方都需要去一个一个的改,特别是这种HTTP基础的服务,引用量甚是惊人,修改起来就是要炸!
于是人们想到 通过一个 “工厂”的概念来 让这个 “工厂”生产出 需要的service
public class ServiceFactory{
public static getHttpService(){
retrun new HttpService();
}
}
public class MineActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
HttpService httpService = ServiceFactory.getHttpService();
....
}
}
上面看上去是解决了大部分的问题,如果是这个使用 HttpService 的构造函数 添加了Context ,那么只要在ServiceFactory.getHttpService() 里面的实现增加Context,而不去修改 ServiceFactory在其他activity的应用
public class ServiceFactory{
Context context = MyApplication.getContext();
public static getHttpService(){
retrun new HttpService(context );
}
}
像是解决了问题,但是这里还是需要手工去 MyApplication.getContext()去拿到这个Context,这时候就想,如果Factory 告诉一个“人” 他需要 Context,而context 那个”人”自动 提供就好了。
于是就用到 Dagger 这个玩意,这个玩意。这是一个依赖注入框架,在搞javaee的时候就有过 Spring。这些东西 可以理解为一个强力的工厂模式。 通过 构建一个 依赖关系,统一由 Dagger 来把需要的东西注入到。
Dagger 有两个分支 一个是 Squeue ,一个google分支 Dagger2
我选择的是 Dagger2,这两个分支的区别具体有什么不一样,请百度。。。
如何使用:
Dagger 由以下结构组成
配置Android Studio
配置gradle
project.build
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0-alpha3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //dagger 使用apt
}
}
app.build
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' //dagger使用apt
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
//引入相关dagger相关的依赖
compile 'com.google.dagger:dagger:2.0.2'
compile 'com.google.dagger:dagger-compiler:2.0.2'
//dagger 编译相关
provided 'org.glassfish:javax.annotation:10.0-b28'
}
Module
Component
Inject
用上面的场景来说,需要注入 httpService 到activity中
那么确定了我们的activity 需要 HttpService ,那么大概的提供链为
Module(生产HttpService) <–> Component(连接activity 与 module的关系)<–> activity(通过inject 注入 HttpService)
构建Module ,提供出HttpService
@Module
public class ServiceModule{
@Inject
public ServiceModule(){
}
@Provides
HttpService getHttpService(){
return new HttpService();
}
}
这里有两个注解 @Module @Provides
@Module 标明他是 一个Module,
@Provides 在需要向外提供的方法 注解,比如现在要对外提供HttpService 通过 getHttpService方法
接下来可以用于 连接关系 的Component
@Component(modules={ServiceModule.class})
public interface ActivityComponent{
void inject(MainActivity activity);//参数必须是 MainActivity 类型,如果你要其他activity 也必须明确到 那个类,因为在运行时的时候 是通过 反射 来注入的,所以这个需要找这个类下需要注解的东西
HttpService httpService()
}
inject 方法声明可以通过 绑定 MainActivity 来实现注入,至于可以注入什么?可以看到 Component暴露出来 有返回值的方法,和 绑定的Module提供带有 @Provides 的东西,不过一般来说 对于activity他只和 Component 打交道,不直接跟 Module 有接触,他是不可能知道 Module 有什么东西,所以基本上activity认定可以注入的 有 Component 中 方法返回值
注意 :Component 绑定的Module 必须实现 Component 中定义返回值方法,但是 并不用直接 实现Component 。就如上面一样 ServiceModule 并没用直接实现 Component 而是里面包含有返回HttpService的方法 并 @Provides 而已。
下面来编写Activity
public class MineActivity extends Activity{
@Inject //标致 这个由Dagger 注入
HttpService mHttpService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DaggerActivityComponent.builder().build().inject(this);//把当前的activity 丢进Component 让他自动注入给 mHttpService
....
mHttpService.doPost("http://a.com");
....
}
}
或许大家很很奇怪 DaggerActivityComponent 这个是那里来的,这个是由Dagger2 自动编译出来的 会根据你写的Component 来自动生成 Dagger前缀的Component ,这个就是Dagger帮你自动实现的 Component.
然后通过 inject activity 进入,然后查找对应 的@Inject