Android 与Inject(依赖注入)的不解之缘
依赖注入(DI)
有些人说Android使用依赖注入是因为很多J2EE的人带来的异域思想, 满天飞的注解
让人莫不找头脑, 使简单的行为变得复杂, 表面简化, 实则复杂.
但是在使用其一段时间后, 确实还是挺不错的. 正如其思想之精髓, 让你只关注结果,而忽略制作过程, 呵呵, 跟周星驰
他老母恰巧相反.
那么下面就讲讲Android开发中常常的用的一些DI框架, 来简化亲们的开发流程吧.
Butterknife
Butterknite是一个专注于简化View相关使用的DI框架, 而且其不像Spring
一样使用反射, 而通过预编译来做到注入效果, 大大降低了消耗, 绿色环保, 下面就来讲讲他的使用, 其实很简单.
配置:
由于目前基本都是用Android Studio开发, 这里添加gradle的依赖就行了
1 | compile 'com.jakewharton:butterknife:6.0.0' |
使用方法:
- 初始化注入
1 |
|
compile 'com.squareup.dagger:dagger:1.2.2'
compile 'com.squareup.dagger:dagger-compiler:1.2.2'
1 |
|
这里的library = true
的意思是可能不会被使用, 这只是一个lib, 默认为false, 如没有被使用会抛错complete = false
的意思是这是一个不完整的moudle, 为何这么说, 可以看出provideLocationManager
的参数没有响应提供值的Providers
呢, 为什么呢, 因为这个Moudle接下来要被另外一个Moudle引用, 所以application这个参数我们将在下一个Moudle里提供.@Provides
是必须要有的注解, 告诉Dagger这个方法就是提供LocationManager
的方法.@Singleton
是标注这是一个单例, 保证了线程安全.
1 | ( |
这个Moudle比较长, 首先使用了include
来包含我们之前定义的Moudle.
而且也可以发现,这个Moudle提供了Context
的Provides
injects
比较重要, 这里指定的class
就是那些需要使用注入对象的类
有些同学可能会有同样类型的对象注入的问题, 问题的解决办法就是使用@Named
来标识其使用的是哪一个@Provides
.
2.将Moudle提供给容器ObjectGraph
(把之前定义的各个对象的构造方法交给Dagger来维护, 它将会把其注入到程序中去)
由于Application一个Android程序只有一个, 可以通过getApplication
获得,那么最佳存放容器与注入的地方就是这里了,请看代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class DemoApplication extends Application {
private ObjectGraph graph;
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(getModules().toArray());
}
protected List<DemoModule> getModules() {
return Arrays.asList(new DemoModule(this));
}
public void inject(Object object) {
graph.inject(object);
}
}
3.使用注入对象
劳烦了半天, 终于可以尝尝甜头了, 下面看看使用的办法, 请看代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class DemoActivity extends Activity {
LocationManager locationManager;
"hehe") (
DaggerYa daggerYa;
DaggerLa daggerLa;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入
((DemoApplication) getApplication()).inject(this);
}
}
使用注入对象的类, 定义的Moudle里面必须要有这个类的声明(injects = xxx.class
), 并且需要调用容器的inject
方法(如加粗部分)
下面就可以通过@Inject
轻松使用无需再构造的对象了, 以后只需要添加injects
, 并且调用inject
方法, 就可以在其他类继续无构造使用提供过Provides
的对象啦
PS:
当然把所有注入对象的构造声明全部放在我们的DemoModule
里面也显得有些繁琐, 实际上Dagger
也支持标准的Java
注入格式. 我们可以直接在自己声明的需要注入的类上面添加注解, 来让Dagger
找到它的构造函数. 如:
1 |
|
在预编译的时候, Dagger
就会通过@Inject
找到DaggerHehe
的构造, 当然DaggerHehe
的参数也都需要注入哦. @Singleton
同样的将该类声明为一个单例了, 并且还少了之前的@Provider
注解, 是不是显得很精简. 赶快去试试吧!