一、Dagger2简介
Dagger2是一个依赖注入框架,所谓的依赖注入,是一种设计模式,能够很大程度地减少代码的耦合度,我们要怎么理解“依赖注入”呢?请看如下:
依赖:当class A 中要调用 class B 的方法,就要实例化这个对象,这就产生了一种依赖关系(A依赖B),如果class A要调用N个类,就要依赖别的类,也就要实例化N次,这就是所谓的依赖。这违背了设计原则中的单一职责原则。如果对设计原则不清楚的同学可以看看这篇文章。六大设计原则
注入:依赖注入,也就是说“将依赖注入到容器”,我们在这可以把上面的class A作为“容器”,class B当做“依赖”。即将B的对象在A中引用即可。
二、Dagger2的作用
Dagger2的作用强大,可以简单归纳为以下三点:- 松耦,降低代码的耦合度
- 类初始化
- 方便测试
//我们一般情况下都是使用new的方式来创建实例,如下:
class HomeActivity extend Activity{
private HomeAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new HomeAdapter(); //创建实例
}
}
当我们使用了Dagger2的时候,就可以改变了我们创建对象的方式。下面用一张图片来介绍一下常用的几个注解及其之间的关系。
Dagger2结构图
- Moudle:里面有许多创建实例的方法。这些方法使用了@Provide注解
- Component:用来关联Module和Container
- Container:在容器中声明需要使用的类,使用@Inject注解表示
以下会附上代码来说明Dagger2的使用。
二、Dagger2的常用注解
- @Inject
在容器中需要使用的的类的地方使用这个注解。例如:
@Inject
HomeAdapter adapter; // 这个变量不能使用private来修饰
@Moudle
定义一个类,这个类用该注解来修饰。例如:在这定义了一个HomeMoudle类,我们使用这个类来获得所需的对象,一个App中可能有多个Moudle来组成。@Provide
我们来Moudle类中声明的方法会使用到这个注解,表示该方法提供返回一个实例。@Component
Component的作用是将Container和Moudle联系起来,它是一个接口。@Singleton
表示该对象是一个单例。@Scope
可以在自定义注解的时候,使用该注解来规定作用范围。
三、Dagger2的使用
1. Dagger2的配置
在builder.gradle(project)文件中
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
在builder.gradle(app)文件
apply plugin: 'com.neenbedankt.android-apt' \\(配置插件,一般写在顶部)
dependencies {
//Dagger2
compile 'com.google.dagger:dagger:2.0'
apt 'com.google.dagger:dagger-compiler:2.0'
compile 'org.glassfish:javax.annotation:10.0-b28' // Java标注
}
2. 创建Moudle
@Moudle
class HomeMoudle{
@Provide
public HomeAdapter provideHomeAdapter(){
return new HomeAdapter();
}
}
3. 创建Compnent
@Component(mouldes = HomeMoudle.class) //通过该方式与moudle关联
public interface HomeComponent{
//需要写一个方法来关联容器,这里的容器是HomeActivity
void inject(HomeActivity activity); //与Container关联
}
4. 在Container中注入(有两种方式可以注入)
class HomeActivity extend Activity{
@Inject
HomeAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/
//DaggerHomeComponent 是HomeComponent的子类,由Dagger2自动实现
//当Moudle中需要用到参数时,可以通过构造方法将参数导入,如HomeMoudle(new HomeMdoule(Context context))
DaggerHomeCompnent.builder().HomeMoudle(new HomeMdoule()).builder().inject(this);
//第二种方式,这是一种简便的注入方式,如果Moudle中没有用到参数的时候可以调用该方法
DaggerHomeComponent.create();
}
}
四、Dagger2的注意事项
1. 在Moudle中,如果有使用到参数,就必须要定义一个提供该参数的方法,否则会报错。如:
@Moudle
class HomeMoudle{
Context context ;
//如果某个实例需要参数,可以利用Moudle的构造方法将参数代入
public HomeMdoule(Context context){
this.context = context;
}
//如果某个实例需要用到参数,必须新定义一个方法来返回该参数,如下ProvideContext;
@Provide
public HomeAdapter provideHomeAdapter(Context context){
return new HomeAdapter(context);
}
//该方法用于返参数
@Provide
public Context provideContext(){
return Context; //此处的Context 是由Moudle的构造函数带进来的,
}
}
//此时在容器中(如 HomeActivity )注入就需要以下写法
public clasee HomeActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注入
DaggerHomeComponent.builder()
.HomeMoudle(new HomeMoudle(this))
.builder.inject(this);//这里的this只上下文
}
2.在Fragment实现注入的时候,要将注入方法写在onActivityCreated中,如:
public class HomeFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//注入
DaggerHomeComponent.builder()
.HomeMoudle(new HomeMoudle(getActivity()))
.builder.inject(getActivity());//这里的this只上下文
}
}