Dagger2多模塊項目Component組織方式選擇(一)

本文適合有必定的Dagger2使用基礎的同窗 android

下一篇:Dagger2多模塊項目Component組織方式選擇(二)git

Dagger2有兩種組織方式依賴(dependencies)和繼承(SubComponent).
對於單模塊簡單項目來講,兩種方式隨意,看我的喜歡,對於多模塊項目來講就要好好選擇了。 github

多模塊項目分兩種:segmentfault

  • 一種是普通多模塊項目,主模塊擁有全部子模塊的直接依賴
  • 另外一種是組件化的項目,單獨模塊開發時主模塊沒有直接依賴子模塊

這裏先給出結論:app

  • 普通多模塊項目使用繼承(SubComponent)
  • 組件化的項目使用依賴(dependencies)

這篇文章咱們先來看第一種,這種方式其實就是Android官方上介紹的ide

假設項目模塊結構以下圖
組件化

在普通多模塊項目中,app直接依賴news與user模塊,能夠直接引用其中的類this

app中放Appcomponent其它模塊用SubComponent繼承Appcomponentgoogle

base模塊spa

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()
    }
}

代碼地址

相關文章
相關標籤/搜索