Kotlin Common篇之八 Dagger?Kodein!

image

首發(fā)于公眾號(hào): DSGtalk1989

最可怕的還是來了,依賴注入一直是一般工程師最最不愿意去碰的東西。復(fù)雜,不易理解。但是不得不承認(rèn),使用起來真的很方便。本章節(jié)將不盡量不涉及原理說明,只介紹依賴注入使用。

相比較而言,可能知道Dagger的人會(huì)多很多。但是這里選擇用Kodein作為kotlin項(xiàng)目的依賴注入框架,除了kodein本身是用kotlin寫的之外,還有他更加容易理解的使用方式,我們多說無益,跟著我來一起上手吧!

第一步,添加依賴

// 基礎(chǔ)組件
  implementation 'org.kodein.di:kodein-di-generic-jvm:6.1.0'
  // Android擴(kuò)展組件
  implementation 'org.kodein.di:kodein-di-framework-android-core:6.1.0'
  // support擴(kuò)展組件,我的項(xiàng)目中用到了v4包的Fragment,因此我需要它
  implementation 'org.kodein.di:kodein-di-framework-android-support:6.1.0'

第二步,在主application中添加實(shí)現(xiàn)KodeinAware接口

class FrameApplication : Application(), KodeinAware {

      override val kodein: Kodein = Kodein.lazy {  }
  
}

實(shí)現(xiàn)之后會(huì)要求你必須復(fù)寫kodein屬性,我們直接定義成延遲屬性lazy,具體見委托。我們需要在lazy中做一些初始化的工作,其實(shí)顯而易見了,就是我們將要注入的依賴。

第三步,定義Module

我們挑一個(gè)最最常用的注入例子,Retrofitservice注入。這里建議大家把所有需要注入的通用module,放在同一個(gè)地方,比如ModuleFactory.kt

kodein針對(duì)module的語法如下

val moduleName = Kodein.Module(MODULE_TAG) {
    bind<injectClass>() with singleton { init it }
    
    instance<haveInjectedClass>
            .haveInjectedClassFun(instance())
}

不知道直接這么寫,大家可否理解。首先module是一個(gè)屬性或者方法都可以,指向的Kodein.Module需要傳入一個(gè)TAG字符串,然后我們將需要注入的對(duì)象類型綁定,并在singleton后面的lambda表達(dá)式中對(duì)注入對(duì)象進(jìn)行初始化。

針對(duì)已經(jīng)聲明過注入的類型對(duì)象,我們直接可以使用instance帶注入類型的方式當(dāng)成注入對(duì)象來使用,并且在相關(guān)方法中一旦需要傳入已經(jīng)注入過的對(duì)象,直接調(diào)用instance()即可,框架會(huì)幫我們找到相應(yīng)的對(duì)象。

所以這邊okHttpModule的注入如下:

/**
   * OKHTTP module
   */
  val httpClientModule = Kodein.Module(HTTP_CLIENT_MODULE_TAG) {
      bind<Retrofit.Builder>() with singleton { Retrofit.Builder() }
      bind<OkHttpClient.Builder>() with singleton { OkHttpClient.Builder() }
  
  
      bind<Retrofit>() with singleton {
  
          instance<Retrofit.Builder>()
              .baseUrl(AppConfig.BASE_URL)
              .addConverterFactory(GsonConverterFactory.create())
              .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
              .client(instance())
              .build()
      }
  
      bind<OkHttpClient>() with singleton {
  
          //打印請(qǐng)求log
          val logging = HttpLoggingInterceptor()
          logging.level = if (BuildConfig.DEBUG) {
              HttpLoggingInterceptor.Level.BODY
          } else {
              HttpLoggingInterceptor.Level.NONE
          }
  
          instance<OkHttpClient.Builder>()
              .addInterceptor(logging)
              .addInterceptor(headerInterceptor())
              .build()
      }
  }

第四步,import module

在application中,直接做import

override val kodein: Kodein = Kodein.lazy {
      import(androidCoreModule(this@FrameApplication))
      import(androidXModule(this@FrameApplication))

      import(httpClientModule)
}

這里我們還引入了androidCoreModuleandroidXModule,相關(guān)核心控件的context,甚至很多的系統(tǒng)服務(wù)。

第五步,使用注入

Activity中,我們同樣需要實(shí)現(xiàn)KodeinAware接口,并且復(fù)寫屬性kodein

override val kodein by org.kodein.di.android.kodein()

Ok,就這么簡(jiǎn)單。接下去所有需要使用到注入的都是同樣的操作。

val serviceManager: ServiceManager by instance()

val userDao: UserDao by instance()

所有的屬性,我們都只要指出他是什么類型,同時(shí)委托給instance()即可,框架會(huì)幫我們自動(dòng)的初始化。

BTW,有同學(xué)跟我反應(yīng),有個(gè)注入框架比上面講的kodein還好用,叫做koin,大家可以也看一下哦,之后抽空我來做橫向比較。有個(gè)框架很好用,有空就訪問這個(gè)鏈接koin

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容