Dagger2-Scope
Scope–能为我们提供什么
几乎所有的项目都会使用单例-比如API Client,DatabaseHelper,Analytic Manager等。因为依赖注入,所以我们不用关心实例化。我们不应该在代码里考虑如何获取这些对象。取而代之的是@Inject
会给我们提供应该要提供的实例。
在Dagger2的Scope机制使得让一个类保持单例让他的存活周期跟Scope一样长。例如在实际中一个在@ApplicationScope
的实例的存货周期跟Application的生命周期是一样的。@ActivityScope
的存活周期跟Activity的生命周期相同(比如我们可以在同一个Activity下所有的Fragment共享单例)。
简单说:Scopes给我们创建了一种”局部单例“,生命周期取决于Scope自己。
但是,Dagger2并没有提供@ActivityScope
和@ApplicationScope
,这些都是要通过@Scope
来自定义。Dagger2默认只提供@Singleton
的Scope注解。
Scope实践
我们要实现比Application/Activity Scope更加复杂的Scope。用GithubClient项目做为解释,项目中用到了三个Scope:
- @Singleton - ApplicationScope
- @UserScope - 用来联系用户的实例类的Scope(已经登录的用户)
- @ActivityScope - 用来做与Activity生命周期相同的类的Scope(presenters 在我们的例子中)
引入的@UserScope
跟前一篇文章的方案有不同之处。从用户体验的角度来说他没有提供任何帮助。但是从架构角度来说,他帮助我们在不需要传入任何intent参数的情况下为我们提供User
实例。
并且那些需要user数据的类(RepositoriesManager
类在这个例子中)能通过把User
作为构造器函数拿到User
。并且是在需要的时候去初始化,而不是在App启动的时候去初始化。这意味着:RepositoriesManager
会在我们通过GithubApi拿到用户之后去做初始化(在RepositoriesListActivity
呈现之前)。
这是简单的一个我们应用的Scopes和Component的示意图:
Singleton(ApplicationScope)是存活周期最长的Scope。
UserScope作为ApplicationScope的子Scope,他可以访问访问父Scope的对象。
ActivityScope也是如此,可以拿到UserScope跟ApplicationScope的对象。
Scope 生命周期示例
单例的生命周期是从app启动后的App的存活时间。
UserScope的创建是从我们通过GithubApi拿到User
开始(真实情况下,实在用户登录后),并在我们回到SplashActivity后被销毁(真实情况下,是在用户登出后)。当新登录一个用户,会产生另外一个UserScope.
每个ActivityScope
存活时间跟他所对应的Activity是一样的。
实现
在Dagger2中,Scope的实现归结于对Component的正确设置。一般情况下有两种设置:
1.使用
Subcomponent
注解 2.使用Component依赖
两者最大的区别在于对象图的共享。Subcomponent可以访问他们Parenent Component的所有对象图,而Component依赖只能通过Component暴露对象接口来访问。
这里选择第一种实现AppComponent
:
他会是其他SubComponent的根Component:UserComponent跟ActivitysComponents。我们去掉了上一章的依赖对象的接口暴露。Subcomponent可以直接访问全部的对象。
作为代替,我们新增了两个方法:
UserComponent plus(UserModule userModule);
SplashActivityComponent plus(SplashActivityModule splashActivityModule);
这表示我们可以从AppComponent
创建两个子Components:UserComponent
与SplashActivityComponent
。两个子Components都可以访问AppComponent
的Module的依赖。
这些方法的命名规则是:返回类型是subcomponent类,方法名字随意,参数是这个subcomponent的module
比如:UserComponent
需要一个module(他通过plus传入)。这样,我们通过增加一个新生成的对象module,集成AppComponent
图标:
UserComponent从AppComonent引用的对象都是单例,但是UserModule即UserComponent的那部分,创建的对象是”局部单例“。
在这里比较重要的是我们要负责UserComponent
的生命周期。所以我们应该关心他的初始化和释放,在GithubClient
的例子中,我们新增两个方法:
createUserComponent()
方法我们会从GithubApi(在SpliashActivity
中)获取到User
对象时调用;releaseUserComponent()
方法会在我们从RepositoriesListActivity
(这个时候我们不再需要user scope了)中退出时调用。