Dagger2,是一个google的依赖注入框架,在项目中有使用,但一直不是很理解使用的过程,现在要做到的是,理解为什么要这么使用。
在我们需要组合一个对象的的时候就需要手动new出该对象,但当我们需要修改这个对象的构造时,就需要对这个被组合的类进行修改,这样就耦合了。我们思考这样一个问题,可否实现这样一种方式,创建一个容器,当我们需要这个对象时,直接从容器中去取。而这个容器就是Dagger2要帮我们做的。
使用Dagger2,我理解为有以下几个部分。
1 调用者(被注入者)
2 注入者 (注入的对象)
3 实例化部分
4 注入桥梁(将实例化的对象注入到调用者中)
我个人的理解是这样的, 从右向左, 实例化部分会创建注入者的对象,先放在实例化部分备用,注入桥梁的作用是将对应的对象,从实例化部分中取出然后注入到调用者中去,实现对象的绑定。
直接用例子 说明了:
入过我们想在Activity中添加一个Presenter,正常情况下我们会在Activity中new出这个对象。
public class MainPresenter {
private MainView view;
public MainPresenter(MainView view){
this.view = view;
}
public void loadData(){
view.setData();
}
}
public class MainActivity extends AppCompatActivity implements MainView {
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainPresenter = new MainPresenter(this);
mainPresenter.loadData();
}
@Override
public void setData() {
}
}
现在的MainPresenter只有这一处使用,但如果多次使用的话,通过这样的方式,如果要修改多处创建的地方,所有的使用者和MainPresenter都存在直接的耦合关系。
使用Dagger2注入的方式。
方式一:实例化部分提供MainPresenter
@Module
public class MainModule {
private final MainView mainView;
public MainModule(MainView view) {
mainView = view;
}
@Provides
MainPresenter provideMainPresenter(){
return new MainPresenter(mainView);
}
}
@Module注解的部分对应实例化部分。
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
}
@Component定义的部分对应桥梁。指定注入的对象MainActivity
@Inject
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
mainPresenter.loadData();
}
在MainActivity中使用,需要添加 @Inject注解,并指定MainModule;
方式二:Module提供MainView,实例化部分交由Dagger2创建
@Module
public class MainModule {
private final MainView mainView;
public MainModule(MainView view) {
mainView = view;
}
@Provides
MainView provideMainView() {
return mainView;
}
}
不同的部分就是我们provide的不是直接创建的MainPresenter而是mainView。
@Inject
public MainPresenter(MainView view){
this.view = view;
}
这时在MainPresenter中的对应参数的构造添加 @Inject注解。使用时与方式一无异。
方式三:通过注入桥梁直接返回对象实例
确切的说 这个不能说是方式三,方式三可以与前两个方式组合使用。注入桥梁的定义方式不同。
@Component(modules = MainModule.class)
public interface MainComponent {
MainPresenter getPresenter();
}
只要在Module中能找到合适的返回类型,或者在标记了@Inject的构造相匹配(参数也符合要求,能找到对应的参数,就可以通过桥梁直接获取对象实例。
使用时:
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainPresenter = DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.getPresenter();
mainPresenter.loadData();
}
直接获取对象实例,不需要使用@Inject注解,但不推荐这种方式,这样会降低注入代码的可读性。
还需要再提到一个Lazy类
Lazy类是实现懒加载,调用的时候才创建实例,通过Lazy对象实现,得到对象的实例使用get()方法。
获取时包上Lazy。使用时先get。
@Inject
Lazy<MainPresenter> mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
mainPresenter.get().loadData();
}
就先到这吧
网友评论