Android使用dagger2包各,語言為kotlin

使用依賴注入的好處在這里不細(xì)說摘仅,我們重點了解如何在Android項目中使用dagger2

1. 引入dagger2

 implementation 'com.google.dagger:dagger-android:2.25.2'
 implementation 'com.google.dagger:dagger-android-support:2.25.2'
    // if you use the support libraries
 implementation 'com.google.dagger:dagger:2.25.2'
 kapt 'com.google.dagger:dagger-compiler:2.25.2'
 kapt 'com.google.dagger:dagger-android-processor:2.25.2'

注意如果項目級別的gradle文件中沒有

apply plugin: 'kotlin-kapt'

要記得加上,不然會報錯

2.聲明提供方

我們可以在一個類的構(gòu)造方法上加上@Inject來表明當(dāng)有一個類使用到我們這個類的實例的時候问畅,可以調(diào)用我們這個用注解標(biāo)記的構(gòu)造方法來生成一個

class Model constructor(
    val uuid: String
) {
    @Inject
    constructor() : this(UUID.randomUUID().toString())
}

3.聲明使用方

在需要提供注入的類的屬性上使用@Inject來表明我們這個屬性需要dagger2來注入

class MainActivity : AppCompatActivity() {


    @Inject
    lateinit var model1: Model


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

4.聲明注入器

現(xiàn)在我們有了依賴的提供方和依賴的使用方娃属,那么如何把這兩者結(jié)合起來,讓依賴注入到使用者需要的屬性上呢护姆?我們這里就需要用到@Component注解來生成一個注解器矾端。

我們用@Component來注解一個接口,dagger2會在編譯時自動生成一個Dagger+類名的實現(xiàn)類實現(xiàn)依賴注入卵皂。具體使用方法有以下兩種:

- Members-injection methods

該方法有一個參數(shù)秩铆,這個參數(shù)表示需要注入的對象,告知dagger2去尋找需要的依賴并注入到對象的屬性上灯变,例如

@Component
interface MainComponent {

    fun inject(mainActivity: MainActivity)
}

- Provision methods

聲明一個不需要參數(shù)但有返回值的方法殴玛,返回一個需要被注入的依賴,返回對象由使用者自行處理添祸,例如:

@Component
interface SecondComponent {

    fun getModel(): Model
}

5.使用注入器注入依賴

當(dāng)我們聲明了依賴的提供方滚粟、依賴的使用方和注入器,我們就可以使用依賴注入了膝捞。編譯項目坦刀,會生成Dagger+注入器為類名的注入器的實現(xiàn)類。

class MainActivity : AppCompatActivity() {


    @Inject
    lateinit var model1: Model


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        DaggerMainComponent.builder().build().inject(this)
        model1.uuid.log()
    }
}

在注入器注入依賴后蔬咬,我們就可以使用被注入的對象了鲤遥。

6.第三方依賴注入

我們可以使用@Inject來標(biāo)識一個構(gòu)造函數(shù),當(dāng)我們需要這個類的實例時林艘,我們會調(diào)用@Inject標(biāo)識的構(gòu)造方法來創(chuàng)建一個對象盖奈。但是如果我們需要注入的是一個第三方的對象,我們沒有辦法去修改第三方的源碼狐援,我們應(yīng)該怎么辦钢坦?
我們可以使用@Module@Provides來搭配使用:

  • 新建一個module接口究孕,在接口上使用@Module
  • 聲明一個方法, 返回值為我們需要的類型
@Module
class HttpServiceModule {
    @Provides
    fun provideHttpService(): HttpService {
        return HttpService()
    }
}
  • 在注入器的@Component里面添加我們剛才新建的module
@Component(modules = [HttpServiceModule::class])
interface HttpComponent {

    fun inject(httpActivity: HttpActivity)
}

然后就可以正常使用了

7.指定依賴注入

有時我們會遇到這么一種情況爹凹,我們會提供同一個類型的不同的依賴厨诸,比如我們項目中集成了高德地圖和百度地圖,我把兩個地圖的key使用依賴注入的方式來注入到初始化的代碼中禾酱,在一個module里面聲明了兩個類型都是字符串的key微酬,如何讓dagger2知道我們需要的是哪一個呢?

class KeyActivity : AppCompatActivity() {


    @Inject
    lateinit var key: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_key)
    }
}


@Module
class KeyModule {

    @Provides
    fun provideAmapKey(): String = "amap"


    @Provides
    fun provideBaiduKey(): String = "baidu"
}

@Component(modules = [KeyModule::class])
interface KeyComponent {

    fun inject(keyActivity: KeyActivity)
}

我們可以使用@Named注解颤陶,在注解提供的方法上和需要注入的屬性上使用相同的字符串颗管,通過字符串匹配,讓dagger2知道我們要的是哪個滓走。例如:

class KeyActivity : AppCompatActivity() {


    @Named("amap")
    @Inject
    lateinit var key: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_key)



        DaggerKeyComponent.create().inject(this)

        key.log()
    }
}


@Module
class KeyModule {

    @Named("amap")
    @Provides
    fun provideAmapKey(): String = "amap"


    @Named("baidu")
    @Provides
    fun provideBaiduKey(): String = "baidu"
}

@Component(modules = [KeyModule::class])
interface KeyComponent {

    fun inject(keyActivity: KeyActivity)
}

當(dāng)然有些人覺得用字符串來標(biāo)識指定注解不太靠譜垦江,因為字符串可能會寫錯。我們可以使用@Qualifier注解來標(biāo)識我們自己創(chuàng)建的注解搅方,當(dāng)提供方的自定義注解和使用方的自定義注解相同時比吭,dagger2就會為我們做出正確的注入。

class Dog : Animal {
    override fun toString(): String {
        return "dog"
    }
}

class Cat : Animal {
    override fun toString(): String {
        return "cat"
    }
}


@Module
class AnimalModule {


    @DogAnimal
    @Provides
    fun provideDog(): Animal = Dog()

    @CatAnimal
    @Provides
    fun provideCat(): Animal = Cat()
}


@Component(modules = [AnimalModule::class])
interface AnimalComponent {

    fun inject(animalActivity: AnimalActivity)
}

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class DogAnimal

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class CatAnimal

class AnimalActivity : AppCompatActivity() {


    @CatAnimal
    @Inject
    lateinit var animal: Animal

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_animal)


        DaggerAnimalComponent.create().inject(this)

        animal.toString().log()

    }
}

8.單例

考慮一下代碼姨涡,一個使用方需要使用兩個依賴梗逮,這兩個依賴類型一樣,他們會是同一個對象嗎绣溜?或者說在注入的時候會調(diào)用幾次帶有@Inject的構(gòu)造方法慷彤?

class PeopleActivity : AppCompatActivity() {

    @Inject
    lateinit var people1: People

    @Inject
    lateinit var people2: People


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_people)


        DaggerPeopleComponent.create().inject(this)

        "$people1 $people2 ${people1 === people2}".log()
    }
}


class People @Inject constructor()


@Component
interface PeopleComponent {

    fun inject(peopleActivity: PeopleActivity)
}

考慮下上面的輸入是什么?上面的輸入是

com.ke.dagger2_demo.People@5aa9f47 com.ke.dagger2_demo.People@e17a374 false

但是有些時候我們不希望每次使用依賴的時候都去創(chuàng)建一個對象怖喻,比如使用我們的http client底哗,我們希望全局有且僅有唯一一個http client,那么這時我們應(yīng)該怎么做锚沸?
我們可以使用@Singleton注解放在我們希望是單例的類名上跋选,告訴dagger2在創(chuàng)建該類實例的時候只能創(chuàng)建一次。

@Singleton
class People @Inject constructor()

注意一點哗蜈,在對應(yīng)的注入器上同樣要加上@Singleton注解

@Singleton
@Component
interface PeopleComponent {

    fun inject(peopleActivity: PeopleActivity)
}

晚上上述操作后在看看我們的輸入

com.ke.dagger2_demo.People@5aa9f47 com.ke.dagger2_demo.People@5aa9f47 true

加了@Singleton注解后前标,兩個依賴是同一個對象,不會在使用依賴的時候額外創(chuàng)建了距潘。

額外提一點炼列,@Singleton@Scope的一個實現(xiàn),類似@Named@Qualifier一樣音比,如果你不喜歡Singleton這個名字俭尖,可以自己創(chuàng)建一個自定義注解并用@Scope來標(biāo)識。

9.@Binds

在實際項目中,我們可能會遇到這么一種情況稽犁,我們需要注入的依賴類型是抽象的焰望,我們可以在指定的module中利用@Provide注解一個方法,接收一個實現(xiàn)類對象已亥,返回的類型是抽象的熊赖,例如:

class WeaponActivity : AppCompatActivity() {

    @Inject
    lateinit var weapon: Weapon


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_weapon)

        DaggerWeaponComponent.create().inject(this)

    }
}


interface Weapon {
    fun attack()
}

class Gun @Inject constructor() : Weapon {
    override fun attack() {
        "gun attack".log()
    }
}

class Sword @Inject constructor() : Weapon {
    override fun attack() {
        "sword attack".log()
    }
}


@Module
class WeaponModule {

    //接收一個實現(xiàn)類的對象,返回抽象類型
    @Provides
    fun provideWeapon(gun: Gun): Weapon {
        return gun
    }
}

@Component(modules = [WeaponModule::class])
interface WeaponComponent {
    fun inject(weaponActivity: WeaponActivity)
}

我們在這里可以用@Binds注解來簡化這一步驟虑椎,把module中的方法改為抽象方法秫舌,module改為抽象類,然后把方法前綴provide改成bind绣檬,@Provide注解修改成@Binds,就可以起到相同的功能嫂粟。

@Module
abstract class WeaponModule {
    

    @Binds
    abstract fun bindWeapon(gun: Gun): Weapon

}

10.注入到Set中

如果我們需要注入的不是單個對象娇未,而是一個集合,例如:

@Inject
lateinit var carSet: Set<Car>

我們應(yīng)該怎么做呢星虹?
我們可以利用@IntoSet方法零抬,把module提供的依賴打包成Set集合注入到我們需要的地方,例如:

class IntoSetActivity : AppCompatActivity() {


    @Inject
    lateinit var carSet: Set<Car>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_into_set)

        DaggerCarComponent.create().inject(this)

        carSet.forEach {
            it.toString().log()
        }

    }
}


data class Car(val name: String)

@Module
class CarModule {

    @Provides
    @IntoSet
    fun provideA(): Car {
        return Car("A")
    }

    @Provides
    @IntoSet
    fun provideB(): Car {
        return Car("B")
    }
}

@Component(modules = [CarModule::class])
interface CarComponent {

    fun inject(intoSetActivity: IntoSetActivity)
}

11.注入到Map中

如果我們需要注入的對象類型是一個map宽涌,我們也能注入嗎平夜?可以的,和注入到Set類似卸亮,我們只需要把@IntoSet修改成@IntoMap忽妒,我們就可以,并且需要指定key兼贸。代碼如下:

class IntoMapActivity : AppCompatActivity() {


    @Inject
    lateinit var foodMap: Map<String, Food>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_into_map)

        DaggerFoodComponent.create().inject(this)


        foodMap.forEach {
            "key = ${it.key} , value = ${it.value}".log()
        }

    }
}


data class Food(val name: String)

@Module
class FoodModule {

    @IntoMap
    @Provides
    @StringKey("apple")
    fun provideApple(): Food {
        return Food("apple")
    }


    @IntoMap
    @Provides
    @StringKey("milk")
    fun provideMilk(): Food {
        return Food("milk")
    }
}

@Component(modules = [FoodModule::class])
interface FoodComponent {
    fun inject(intoMapActivity: IntoMapActivity)
}

12.運行時注入

如果一個提供方的構(gòu)造函數(shù)包含一個參數(shù)段直,并且這個參數(shù)的具體的值只有在程序運行的時候才知道,比如溶诞;

class RuntimeInjectActivity : AppCompatActivity() {


    @Inject
    lateinit var bike: Bike

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_runtime_inject)

        DaggerBikeComponent.builder().bikeModule(BikeModule(100))
            .build().inject(this)

        "bike price = ${bike.price}".log()

    }
}


data class Bike(val price: Int)

我們需要給activity注入一個bike對象鸯檬,但是bike的價格只有在運行的時候才知道,我們不能直接在Bike類的構(gòu)造方法上加上@Inject注解螺垢,因為我們沒法提供價格喧务,我們也不能使用無參數(shù)的Provide方法,因為創(chuàng)建Bike對象必須提供一個價格枉圃,那么我們該怎么做功茴?我們可以在創(chuàng)建Module的時候提供一個參數(shù),在Provide方法里面把這個價格給傳入到Bike的構(gòu)造方法里面孽亲,如下:

@Module
class BikeModule(private val price: Int) {


    @Provides
    fun provideBike(): Bike {
        return Bike(price)
    }
}

完成例子如下:

class RuntimeInjectActivity : AppCompatActivity() {


    @Inject
    lateinit var bike: Bike

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_runtime_inject)

        DaggerBikeComponent.builder().bikeModule(BikeModule(100))
            .build().inject(this)

        "bike price = ${bike.price}".log()

    }
}


data class Bike(val price: Int)


@Module
class BikeModule(private val price: Int) {


    @Provides
    fun provideBike(): Bike {
        return Bike(price)
    }
}

@Component(modules = [BikeModule::class])
interface BikeComponent {

    fun inject(runtimeInjectActivity: RuntimeInjectActivity)
}

13.BindsInstance

在正常情況下痊土,如果我們的module里面的某個Provide方法在創(chuàng)建需要注入的對象的時候需要另外一個對象,例如下面創(chuàng)建Computer對象的時候需要用到Application對象墨林,我們可以通過構(gòu)造方法來傳入一個Application對象赁酝,在創(chuàng)建Component對象的時候調(diào)用

.computerModule(ComputerModule(application))

來傳入Module犯祠。

class BuilderActivity : AppCompatActivity() {


    @Inject
    lateinit var computer: Computer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_builder)


        DaggerComputerComponent
            .builder()
            .computerModule(ComputerModule(application))
            .build().inject(this)
    }
}


data class Computer(val name: String)


@Module
class ComputerModule(private val application: Application) {

    @Provides
    @Singleton
    fun provideComputer(): Computer {
        return Computer(application.packageName)
    }
}

@Singleton
@Component(modules = [ComputerModule::class])
interface ComputerComponent {


    fun inject(builderActivity: BuilderActivity)

}

那么我們有別的方式在Module的Provide方法中提供需要的對象來創(chuàng)建我們要注入的對象嗎?
有的酌呆,我們先改造我們Module里面的Provide方法

@Module
class ComputerModule {

    @Provides
    @Singleton
    fun provideComputer(application: Application): Computer {
        return Computer(application.packageName)
    }
}

我們可以看到衡载,Application對象是作為方法參數(shù)傳入到provideComputer方法里面,意味著我們需要提供一個Application對象∠对現(xiàn)在我們再來改造我們的Component注入器:

@Singleton
@Component(modules = [ComputerModule::class])
interface ComputerComponent {


    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): ComputerComponent


    }

    fun inject(builderActivity: BuilderActivity)

}

我們通過@Component.Builder注解來標(biāo)識我們要自己創(chuàng)建Component的構(gòu)造器(Builder)痰娱,在通過** @BindsInstance**來告訴構(gòu)造器Module需要的Application是通過這個方法傳入的,那么我們的注入方法就變成了

DaggerComputerComponent.builder()
            .application(application)
            .build()
            .inject(this)

14. SubComponent

我們有時會遇到這么一種情況菩收,一個module的provide方法的參數(shù)是另外一個module的provide的方法的返回值梨睁,比如:

class Member

class MemberA @Inject constructor(val member: Member)

@Module
class MemberModule {


    @Provides
    fun provideMember(): Member {
        return Member()
    }
}


@Module
class MemberAModule {

    @Provides
    fun provideMemberA(member: Member): MemberA {
        return MemberA(member)
    }
}

我們要創(chuàng)建MemberA對象,需要一個Member對象娜饵,但是Member對象是另外一個Module提供的坡贺,我們這時應(yīng)該怎么辦?我們有以下兩種方法:

  • Component dependencies
    我們可以在MemberComponent中顯式暴露Member對象箱舞,并在MemberAComponent中聲明依賴MemberComponent遍坟,代碼如下:
@Component(modules = [MemberModule::class])
interface MemberComponent {


    //暴露member對象,方便其他component調(diào)用
    fun member(): Member

}

@Component(modules = [MemberAModule::class], dependencies = [MemberComponent::class])
interface MemberAComponent {

    fun inject(subComponentActivity: SubComponentActivity)
}

在注入的時候晴股,我們先創(chuàng)建被依賴的Component愿伴,在創(chuàng)建DaggerMemberAComponent的時候依次傳入MemberAModule對象和DaggerMemberComponent

val daggerMemberComponent = DaggerMemberComponent.create()


        DaggerMemberAComponent
            .builder()
            .memberAModule(MemberAModule())
            .memberComponent(daggerMemberComponent)
            .build()
            .inject(this)
  • Subcomponent
    我們也可以利用Subcomponent,在MemberComponent中聲明一個返回值為MemberBComponent的方法电湘,傳入的參數(shù)為MemberBModule隔节,在MemberBComponent上把@Component換成@Subcomponent注解,其余的和@Componen一樣寂呛,代碼如下
@Component(modules = [MemberModule::class])
interface MemberComponent {

    fun createSub(): MemberBComponent

}



@Subcomponent(modules = [MemberBModule::class])
interface MemberBComponent {

    fun inject(subComponentActivity: SubComponentActivity)
}

注意在注入的時候官帘,利用daggerMemberComponent來創(chuàng)建我們的daggerMemberComponent來完成注入

        val daggerMemberComponent = DaggerMemberComponent.create()

        daggerMemberComponent.createSub().inject(this)

15.Subcomponent.Builder

和前面提到的@Component.Builder一樣,Component關(guān)聯(lián)的Module的一個Provide方法需要一個參數(shù)昧谊,我們可以自己去創(chuàng)建一個Builder刽虹,并通過@BindsInstance來注解一個方法來傳入?yún)?shù)

@Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): ComputerComponent


    }

同樣,在SubComponent中呢诬,我們同樣可以利用類似的方法來傳入?yún)?shù)給Module來創(chuàng)建我們需要的依賴涌哲,實現(xiàn)這一目標(biāo)需要以下幾個步驟

  • SubComponent內(nèi)部創(chuàng)建一個Builder接口,然后創(chuàng)建兩個方法尚镰,一個方法傳入我們Module需要的參數(shù)阀圾,返回值為Builder類型,并且在方法上加上@BindsInstance注解狗唉;另一個方法返回SubComponent初烘,如下
@Subcomponent(modules = [SonModule::class])
interface SonComponent {

    fun inject(subComponentBuilderActivity: SubComponentBuilderActivity)


    @Subcomponent.Builder
    interface Builder {

        fun build(): SonComponent

        @BindsInstance
        fun name(name: String): Builder
    }
}
  • Component創(chuàng)建一個返回類型為我們剛才新建的Builder接口的方法
@Component(modules = [FatherModule::class])
interface FatherComponent {

    fun createSonBuilder(): SonComponent.Builder
}
  • 在注入的時候,先創(chuàng)建Component,然后調(diào)用Component的創(chuàng)建SubComponentBuilder的方法來創(chuàng)建Builder肾筐,再利用Builder創(chuàng)建SubComponent
DaggerFatherComponent.builder().build().createSonBuilder().name("hankuke").build()
            .inject(this)

以上就是dagger2的內(nèi)容哆料,鏈接在這里
下面我們在講dagger.android,主要是和Android相關(guān)的東西

16.在安卓中使用注入

我們可以在Android里面按照如下的方式完成注入:

DaggerMainComponent
            .builder()
            .build()
            .inject(this)

但是這么寫一是很臃腫吗铐,幾乎每個需要注入的地方都要這么寫东亦,而是幾乎每個需要注入的地方代碼都一樣,顯得有些不太好唬渗。當(dāng)然在Android里面典阵,dagger2提供了更簡單的方式,我們可以按照以下幾個步驟來完成Android中的注入:

  • AppComponent中引入AndroidInjectionModule
@Singleton
@Component(modules = [AndroidInjectionModule::class,MainActivityModule::class])
interface AppComponent {

    fun inject(app: App)
}
  • 聲明ActivitySubcomponent并實現(xiàn)AndroidInjector接口镊逝,然后在SubComponent內(nèi)部聲明一個Factory并實現(xiàn)AndroidInjector.Factory
@Subcomponent(modules = [UserModule::class])
interface MainActivitySubcomponent : AndroidInjector<MainActivity> {

    @Subcomponent.Factory
    interface Factory : AndroidInjector.Factory<MainActivity>
}
  • 編寫我們的UserModule類和User類
data class User(val name: String, val age: Int)

@Module
class UserModule {

    @Provides
    fun provideUser(): User = User("lufei", 20)
}
  • 聲明ActivityModule并和ActivitySubcomponent建立關(guān)聯(lián)壮啊,創(chuàng)建一個方法聲明綁定關(guān)系
@Module(subcomponents = [MainActivityModule_ContributeMainActivity.MainActivitySubcomponent::class])
abstract class MainActivityModule {


@Binds
@IntoMap
@ClassKey(MainActivity::class)
abstract fun bindMainActivityInjectorFactory(factory: MainActivitySubcomponent.Factory): AndroidInjector.Factory<*>
    
    
}
  • 讓我們的Application實現(xiàn)HasAndroidInjector接口,并且注入一個DispatchingAndroidInjector<Any>作為HasAndroidInjector實現(xiàn)方法androidInjector()的返回值

class App : Application(), HasAndroidInjector {


    @Inject
    lateinit var androidInjector: DispatchingAndroidInjector<Any>

    override fun androidInjector(): AndroidInjector<Any> {
        return androidInjector
    }
}
  • ApplicationonCreate()方法里面為Application注入
 override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.create().inject(this)
    }
  • ActivityonCreate()super.onCreate()方法之前為當(dāng)前Activity注入
class MainActivity : AppCompatActivity() {


    @Inject
    lateinit var user: User

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        user.toString().log()
    }
}

-大功告成

17.更加簡化的方式

上面的代碼已經(jīng)可以完成我們的需求撑蒜,但我們還有一種更加簡單的方式來完成對Activity的注入歹啼。
我們先刪除MainActivitySubcomponent類,并在MainActivityModule中聲明下面的方法:

@ContributesAndroidInjector(modules = [UserModule::class])
    abstract fun contributeMainActivity():MainActivity

來代替

 @Binds
 @IntoMap
 @ClassKey(MainActivity::class)
 abstract fun bindMainActivityInjectorFactory(factory: MainActivitySubcomponent.Factory): AndroidInjector.Factory<*>

重新編譯項目减江,我們可以看到dagger自動幫我們生成了一個類MainActivityModule_ContributeMainActivity,類代碼如下:

@Module(subcomponents = MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.class)
public abstract class MainActivityModule_ContributeMainActivity {
  private MainActivityModule_ContributeMainActivity() {}

  @Binds
  @IntoMap
  @ClassKey(MainActivity.class)
  abstract AndroidInjector.Factory<?> bindAndroidInjectorFactory(
      MainActivitySubcomponent.Factory builder);

  @Subcomponent(modules = UserModule.class)
  public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
    @Subcomponent.Factory
    interface Factory extends AndroidInjector.Factory<MainActivity> {}
  }
}

我們可以看到捻爷,我們在未簡化之前的操作辈灼,如聲明SubComponent類,聲明** bindAndroidInjectorFactory方法也榄,聲明@Subcomponent.Factory**工廠類巡莹,都由dagger幫助我們完成了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甜紫,一起剝皮案震驚了整個濱河市降宅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌囚霸,老刑警劉巖腰根,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拓型,居然都是意外死亡额嘿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門劣挫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來册养,“玉大人,你說我怎么就攤上這事压固∏蚶梗” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坎炼。 經(jīng)常有香客問我愧膀,道長,這世上最難降的妖魔是什么点弯? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任扇调,我火速辦了婚禮,結(jié)果婚禮上抢肛,老公的妹妹穿的比我還像新娘狼钮。我一直安慰自己,他們只是感情好捡絮,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布熬芜。 她就那樣靜靜地躺著,像睡著了一般福稳。 火紅的嫁衣襯著肌膚如雪涎拉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天的圆,我揣著相機與錄音鼓拧,去河邊找鬼。 笑死越妈,一個胖子當(dāng)著我的面吹牛季俩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梅掠,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酌住,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阎抒?” 一聲冷哼從身側(cè)響起酪我,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎且叁,沒想到半個月后都哭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡逞带,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年质涛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掰担。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡汇陆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出带饱,到底是詐尸還是另有隱情毡代,我是刑警寧澤阅羹,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站教寂,受9級特大地震影響捏鱼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酪耕,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一导梆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迂烁,春花似錦看尼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至却盘,卻和暖如春狰域,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黄橘。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工兆览, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人塞关。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓抬探,卻偏偏與公主長得像,于是被迫代替她去往敵國和親描孟。 傳聞我的和親對象是個殘疾皇子驶睦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容