Dagger2使用详解
Dagger2简介
Dagger2是Dagger的升级版,是一个依赖注入框架,第一代由大名鼎鼎的Square公司共享出来,第二代则是由谷歌接手后推出的,现在由Google接手维护。
Githu:https://github.com/google/dagger
依赖注入
依赖注入是面向对象编程的一种设计原则,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
举个栗子:
public class ClassA {
private ClassB b
public ClassA(ClassB b) {
this.b = b;
}
}
这里ClassA
的构造函数里传了一个参数ClassB
,随着后续业务增加也许又需要传入ClassC
、ClassD
。试想一下如果一个工程中有5个文件使用了ClassA
那是不是要改5个文件?
这既不符合开闭原则,也不符合单一职责原则,这个时候大杀器Dagger2
就该出场了:
public class ClassA {
@inject
private ClassB b;
public ClassA() {
}
}
通过注解的方式将ClassB b
注入到ClassA
中,可以灵活配置ClassA
的属性而不影响其他文件对ClassA
的使用。
简单的说,就是一个工厂模式,由Dagger
负责创建工厂,帮忙生产instance
。遵从Java规范JSR 330
,可以使用这些注解。现在不研究Dagger2
是如何根据注解去生成工厂的,理解为什么可以实现DI(Dependency Injection)
,如何创建IoC(Inverse of Control)
容器。
Dagger2使用
在实际项目中Dagger2
一般和MVP
模式配合使用
引入Dagger2
api 'com.google.dagger:dagger:2.28.3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.28.3'
定义IView
//IView类
public interface ICommonView {
Context getContext();
}
定义Module
创建一个类CommonModule
@Module
public class CommonModule {
private ICommonView iView;
public CommonModule(ICommonView iView) {
this.iView = iView;
}
@Provides
public ICommonView provideIcommonView() {
return this.iView;
}
}
定义Component
创建一个接口CommonComponent
@Component (modules = CommonModule.class)
public interface CommonComponent {
void inject(LoginActivity activity);
}
定义Presenter
build一下项目,然后在LoginPresenter
里使用@Inject
(@Inject
来自javax
包,不是Dagger2
自定义的)
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();
}
}
使用CommonComponent接口
在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
并没有初始化?这个简单Demo要展示的重点就是loginPresenter
和LoinActivity
彻底解藕,后续无论怎样修改loginPresenter
的构造方法都不需要改动LoinActivity
的代码。如果loginPresenter
构造函数增加参数要改谁的代码呢?当然是CommonModudle
了,其实也很简单,例如增加了一个新参数ImyView
就在CommonModudle.java
中新增一个方法
@Provides
public ImyView provideMyView() {
return myView; // myView是ImyView的实例
}
注意别漏了@Provides
,它是Dagger2
自定义的注解,也是通过它Dagger2
才能正常把新增的参数传入loginPresenter
构造器。
命名规约
@Provides
方法用provide
前缀命名@Module
用Module
后缀命名@Component
以Component
作为后缀
Dagger2总结
Dagger2
是通过依赖注入完成类的初始化,这个过程需要三部分:
- 依赖提供方(生产者)
- 依赖注入容器(桥梁)
- 依赖需求方(消费者)
Dagger2是怎么选择依赖提供的呢,规则是这样的:
步骤1:查找Module中是否存在创建该类的方法
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/29/dagger2-usage-details/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论