本文适合有一定的Dagger2使用基础的同学
下一篇:Dagger2组件化项目Component组织方式选择
Dagger2有两种组织方式依赖(dependencies)和继承(SubComponent).
对于单模块简单项目来说,两种方式随意,看个人喜欢,对于多模块项目来说就要好好选择了。
多模块项目分两种:
- 一种是普通多模块项目,主模块拥有所有子模块的直接依赖
- 另一种是组件化的项目,单独模块开发时主模块没有直接依赖子模块
这里先给出结论:
- 普通多模块项目使用继承(SubComponent)
- 组件化的项目使用依赖(dependencies)
这篇文章我们先来看第一种,这种方式其实就是Android官方上介绍的
假设项目模块结构如下图
在普通多模块项目中,app直接依赖news与user模块,可以直接引用其中的类
app中放Appcomponent其它模块用SubComponent继承Appcomponent
base模块
open class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: BaseApplication
}
}
app模块
注意AppComponent不是放在base模块
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): AppComponent
}
}
@Module
class AppModule {
@IntoSet
@Provides
fun provideString(): String {
return "app"
}
}
class AppApplication : BaseApplication() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.factory().create(this)
}
}
user模块
@Module
class UserModule {
@IntoSet
@Provides
fun provideString(): String {
return "user"
}
}
@UserScope
@Subcomponent(modules = [UserModule::class])
interface UserComponent {
@Subcomponent.Factory
interface Factory {
fun create(): UserComponent
}
}
news模块
@Module
class NewsModule {
@IntoSet
@Provides
fun provideString(): String {
return "news"
}
}
@Subcomponent(modules = [NewsModule::class])
interface NewsComponent {
@Subcomponent.Factory
interface Factory {
fun create(): NewsComponent
}
}
根据SubComponent的原理NewsComponent和UserComponent必须在AppComponent注册它们
@Module(subcomponents = [NewsComponent::class, UserComponent::class])
class AppModule {
@IntoSet
@Provides
fun provideString(): String {
return "app"
}
}
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): AppComponent
}
fun newsComponentFactory(): NewsComponent.Factory
fun userComponentFactory(): UserComponent.Factory
}
要生成NewsComponent和UserComponent必须先得到AppComponent,通过以下方法来创建
val newsComponent = appComponent.newsComponentFactory().create()
val userComponent = appComponent.userComponentFactory().create()
但是显然,user,news模块拿不到appComponent
这里用两个接口来获得
interface NewsComponentProvider {
fun provideNewsComponent(): NewsComponent
}
interface UserComponentProvider {
fun provideUserComponent(): UserComponent
}
让AppApplication实现这两个接口
class AppApplication : BaseApplication(), NewsComponentProvider, UserComponentProvider {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.factory().create(this)
}
override fun provideNewsComponent(): NewsComponent {
return appComponent.newsComponentFactory().create()
}
override fun provideUserComponent(): UserComponent {
return appComponent.userComponentFactory().create()
}
}
然后user,news模块中这样获取
val userComponent = (BaseApplication.instance as UserComponentProvider).provideUserComponent()
val newsComponent = (BaseApplication.instance as NewsComponentProvider).provideNewsComponent()
通常UserComponent与NewsComponent只要一个实例,上面方法每次都他建一个新实例不合适,可以把它们放到一个全局变量中去
object NewsComponentHolder {
val newsComponent: NewsComponent by lazy {
(BaseApplication.instance as NewsComponentProvider).provideNewsComponent()
}
}
object UserComponentHolder {
val userComponent: UserComponent by lazy {
(BaseApplication.instance as UserComponentProvider).provideUserComponent()
}
}
最后在Activity中这样用
class NewsActivity : AppCompatActivity() {
@Inject
lateinit var set: Set<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_news)
NewsComponentHolder.newsComponent.inject(this)
text.text = set.toString()
}
}
class UserActivity : AppCompatActivity() {
@Inject
lateinit var set: Set<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
UserComponentHolder.userComponent.inject(this)
text.text = set.toString()
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。