1.dagger2是what?
dagger2是一个依赖注入的框架,现在是由Google进行维护
2.什么是依赖注入
依赖注入是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的.
example:
public class ClassA{
private ClassB b
public ClassA(ClassB b){
this.b = b }
}
这里的classA的构造函数里传了一个参数ClassB,随着后续业务增加也许又需要传入ClassC等。如果一个工程有很多个文件使用到到了ClassA则需要修改很多个文件
所以这并不符合开闭原则,如果使用Dagger2就会解决此问题
public class ClassA{
@inject
private ClassB b
public ClassA(){
}
}
通过注解的方式将ClassB b注入到ClassA中,可以灵活设置ClassA的属性不影响其他文件对
三、如何使用Dagger2
在实际的项目中一般Dagger2和MVP模式配合使用。
example demo:
模拟登录的业务,Model ,View,Presenter
model:
//model 类
public class User implements Serializable{
private int id;
private String userName;
private String pwd;
}
//Iview 类
public interface ICommonView{
Context getContext();
}
View:
//activity
public class LoginActivity extends AppCompatActivity implements ICommonView {
@BindView(R.id.btn_login)
Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
}
@OnClick(R.id.btn_login) void login(){
}
@Override
public Context getContext() {
return this;
}
}
presenter:
public class LoginPresenter{
ICommonView iView;
public LoginPresenter(ICommonView iView){
this.iView = iView;
}
public void login(User user){
Context mContext = iView.getContext();
Toast.makeText(mContext,"login-----",Toast.LENGTH_SHORT).show();
}
}
2.导入Dagger2
compile"com.google.dagger:dagger:2.14.1"
annotationProcessor"com.google.dagger:dagger-compiler:2.14.1"
注:后面的版本号可以到:https://github.com/google/dagger 获取最新版本
定义一个注解ActivityScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope{
}
这个注解ActivityScope到底是干什么的呢,后面分解
3.创建一个类CommonModule,注意这里用到了刚才定义的@ActivityScope注解
@Module
public class CommonModule{
private ICommonView iView;
public CommonModule(ICommonView iView){
this.iView = iView;
}
@Provides
@ActivityScope
public ICommonView provideIcommonView(){
return this.iView;
}
}
4.创建一个接口CommonComponent
@ActivityScope
@Component (modules = CommonModule.class)
public insterface CommonComponent{
void inject(LoginActivity activity);
}
5.build 一下项目,然后在LoginPresenter里面使用@Inject
public class LoginPresenter{
ICommonView iView;
@Inject
public LoginPresenter(ICommonView iView){
this.iView=iView;
}
public void login(User user){
Context mContext = iView.getContext();
Toast.makeText(mContext,"login.......",Toast.LENGTH_SHORT).show();
}
}
6.在LoginActivity中使用CommonComponent接口
public class LoginActivity extends AppCompatActivity implements ICommonView{
@BindView(R.id.btn_login)
Button btn;
@Inject
LoginPresenter presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
DaggerCommonCompnent.
builder().
commonModule(new CommonModule(this)).
build().
Inject(this);
}
@OnClick(R.id.btn_login) void login(){
presenter.login(new User());
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public Context getContext() {
return this;
}
}
在这里loginPresenter并没有初始化。这里一个重点就是loginPresenter和loginActivity解耦,后续无论是怎么修改loginPresenter得构造方法都不需要改动LoinActivity的代码。而只需要修改CommonModudle
annotationProcessor"com.google.dagger:dagger-compiler:2.14.1"是什么情况?
annotationProcessor是处理注解的工具,是APT(Annotation Processing Tool)
的一种,简单来说注解提供的都是一种“标记”,真正使这些“标记”work的是APT,在build的过程中,APT(就是dagger-compiler)扫描到注解(@Component@Module)生成的.这个过程用下面这张图表示:
那么apt扫描之后会怎样呢?看一下上面demo的build-->generate-->source-->apt目录下面都有什么:
生成了很多文件。就是apt替我们写了很多类和实现方法。这些文件里面的内容墙裂推荐大家看看
ActivityScope是干啥的?怎么里面啥内容都没有?
自定义注解ActivityScope作用是限定被它标记的对象生命周期与对应的Activity相同。其实注解里我们使用了2个元注解
@Scope:标记局部单例;@Retention :指定了它是运行时注解,就是说注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在.
那么,就凭这两个元注解,为啥可以限定被它标记的对象生命周期与对应的Activity相同呢?我们看一下CommonComponent生成类
看看LoginPresenter的构造方法就知道provideIcommonViewProvider的作用了。那为啥说提供了provideIcommonViewProvider单例就保证了生命周期和LoginActivity绑定了呢?如果还不明白就想想LoginPresenter的生命周期。
另一个例子:
https://github.com/brusewu/example-dagger.git