Android依赖注入:Dagger(Part 3)
如果你一直跟着阅读这个系列,那么你已经读过了依赖注入基本知识和依赖注入基础.这篇是最后一篇,将会讲scoped object graphs(指定域的对象图表).
Dagger的指定域对象图表有什么用?
当我们在application对象图表中实例化Dagger单例依赖时,他们一直在内存中,直到程序被销毁.但是有一些单例依赖只在另外一些对象存活时有用.一个简单的例子就是MVP中的view和presenter.大多数时候你只会伴随着activity的存活生命中使用它.在MVP中,一个没有view的presenter是没有用的.我们没必要在activity被销毁后还保留着它.
如何创建一个指定域的对象图表
很简单,我们将会把它添加到application图表.接下来我为每个activity创建一个模型.我们先看看例子:
@Module(
injects = LoginActivity.class,
addsTo = AppModule.class
)
public class LoginModule {
private LoginView view;
public LoginModule(LoginView view) {
this.view = view;
}
@Provides @Singleton public LoginView provideView() {
return view;
}
@Provides @Singleton
public LoginPresenter providePresenter(LoginView loginView, LoginInteractor loginInteractor) {
return new LoginPresenterImpl(loginView, loginInteractor);
}
}
这个模型注入到LoginActivity中,因为它需要将presenter直接注入到activity中,而不是通过构造器来完成.这个模块将会在创建activity图表时被添加到AppModule.这些东西在@Module注解中被声明.
你可以看到,我添加了一个LoginPresenter依赖.它的LoginInteractor将会从一个叫InteractorModule的新模块被注入.它很简单和标准:
@Module(
library = true
)
public class InteractorsModule {
@Provides public FindItemsInteractor provideFindItemsInteractor() {
return new FindItemsInteractorImpl();
}
@Provides public LoginInteractor provideLoginInteractor() {
return new LoginInteractorImpl();
}
}
把它加入到AppModule中,就像你曾经对DomainModule做的一样.
@Module(
injects = {
App.class
},
includes = {
DomainModule.class,
InteractorsModule.class
}
)
public class AppModule {
...
}
接下来我们创建指定域的对象图表.它将通过调用application图表的plus()方法传入新的模型被创建.所以我们可以在App中创建这个方法.
public ObjectGraph createScopedGraph(Object... modules) {
return objectGraph.plus(modules);
}
现在在Activity中我们注入presenter而不是实例化它.
创建图表并注入activity.
public class LoginActivity extends Activity implements LoginView, View.OnClickListener {
@Inject LoginPresenter presenter;
...
private ObjectGraph activityGraph;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
...
activityGraph = ((App) getApplication()).createScopedGraph(new LoginModule(this));
activityGraph.inject(this);
}
@Override protected void onDestroy() {
super.onDestroy();
activityGraph = null;
}
...
}
在onDestroy时将它设置为空,这样它可以被垃圾回收器及时的回收.现在,你已经完成了用Dagger将presenter,view,model注入了.
结论
Dagger是一个强大的工具,但是它的学习曲线比其他库要高所以了解主要概念明白它为什么有用是非常重要的.我希望这一系列的文章可以帮你解决大多数入门的困难.
我更新了例子源码并且创建了一个BaseActivity来封装那些实例化指定域的对象图表的重复的工作.