Android:手寫(xiě)輕量級(jí)的依賴(lài)注入組件

本文未經(jīng)授權(quán)散休,切勿轉(zhuǎn)載

前言

??從業(yè)Android開(kāi)發(fā)快兩年多了次屠,接觸到不同得框架园匹,從最開(kāi)始ButterKnife到后面Kotlin得Kotlin-android-extensions,再到了DataBinding和ViewBinding雳刺,其中印象最深刻不是這類(lèi),也不是像RxJava2這類(lèi)裸违,而是依賴(lài)注入組件諸如Dagger2,再到后來(lái)得Koin煞烫,以及最新的Hilt。那么不如我們自己嘗試看看自己手動(dòng)寫(xiě)能去到什么地步累颂。

前期分析

我大概分析了幾點(diǎn)我們是需要去解決的:</br>一滞详、在基于不進(jìn)行反射下,如何保存好我們預(yù)先初始化的內(nèi)容紊馏,或者我們要初始化的對(duì)象料饥。</br>二、作用域的問(wèn)題朱监,我初始化的Module到底初始化哪個(gè)作用域的問(wèn)題岸啡,還有一種全局都能用的Module。</br>
三赫编、當(dāng)我們的Module包含了存在生命周期的東西巡蘸,如持有LifeOwnwerActivity,或者Fragment等等類(lèi)似的類(lèi)。

快速開(kāi)始

該項(xiàng)目地址在這里Kinit擂送,基于Kotlin進(jìn)行開(kāi)發(fā)的悦荒,以及reified,DSL語(yǔ)法

 startInit {
            enableLog()
            single {  RoomApi.getDao() }
            single {  RetroHttp.createApi(Main::class.java) }
        }
        

如果看過(guò)我那篇文章
Android開(kāi)發(fā): 分享如何利用好Kotlin的特點(diǎn)(一)---- 提高開(kāi)發(fā)效率
應(yīng)該有印象開(kāi)篇就講到如何利用Lazy進(jìn)行全局初始化,當(dāng)時(shí)就是這個(gè)項(xiàng)目的雛形嘹吨。如果我們要在注入到ViewModel內(nèi)的對(duì)象呢,需要在Activity使用這個(gè)Module,由于我們前面分析的第三點(diǎn)搬味,這里使用LifeModule,進(jìn)行生命周期的監(jiān)聽(tīng)蟀拷,然后把對(duì)象從儲(chǔ)存池內(nèi)移走,如下:</br>
Activity.kt

 private val viewModel : MainViewModel by viewModels { ViewModelProvider.AndroidViewModelFactory(application)}
 val module = lifeModule {
            factory(MainViewModel::class.java.name){ this@MainActivity }
        }
 startInit {
            module(viewModel,module)
        }

ViewModel.kt
我們只需要在Activity初始化module第一個(gè)參數(shù)傳入特征對(duì)象碰纬,然后在需要注入的地方,再次把特征對(duì)象傳入lifeOwnerOrNull方法中问芬,所以我建議把這個(gè)特征類(lèi)選擇為注入所在那個(gè)類(lèi)悦析。

 private val repository by lazy {  MainRepository(lifeOwnerOrNull(this))}

MainRepository.kt

class MainRepository(owner: LifecycleOwner?) : BaseRepository(owner)

詳細(xì)可以直接查看我項(xiàng)目的ReadMe,后續(xù)會(huì)補(bǔ)充中文的ReadMe</br>
依賴(lài)方法:App build.gradle

//Core
api("com.github.ShowMeThe.kinit:kinit_core:v0.03")
//Lifecycle-ktx
api("com.github.ShowMeThe.kinit:kinit_lifecycle:v0.03")

還有記得在項(xiàng)目目錄的build.gradle添加

allprojects {
    repositories {
       ........
        maven {
            setUrl("https://jitpack.io")
        }
      
    }
}

核心分析

通過(guò)QuickStart大概已經(jīng)知道如何使用了,那接下來(lái)就分析主要構(gòu)成部分

限定符

其實(shí)這個(gè)限定符就是一個(gè)ConcurrentHashMapKEY的此衅,控制KEY來(lái)控制特征對(duì)應(yīng)存儲(chǔ)不同的Module或者全局初始化對(duì)象

open class Qualifier<D> {

    private var key : D? = null

    private var typeName:String? = ""

    fun setTypeName(typeName: String?){
        this.typeName = typeName
    }

    fun getTypeName() = typeName
    fun getKey() = key

    fun setKeyName(key:D){
        this.key = key
    }

    inline fun<reified T> Qualifier<*>.makeTypeName(){
        setTypeName(T::class.java.name)
    }

    override fun hashCode(): Int {
        return getKey().hashCode() + getTypeName().hashCode()
    }

    override fun equals(other: Any?): Boolean {
        return if(other is Qualifier<*>){
            other.key == this.key && other.typeName == this.typeName
        }else{
            false
        }
    }

    override fun toString(): String {
        return "Qualifier[Key:${key},TypeName:${typeName}]"
    }

}

模塊

模塊里面存儲(chǔ)的也包含一個(gè)ConcurrentHashMap强戴,用于存儲(chǔ)不同的初始化的內(nèi)容,通過(guò)唯一的name炕柔,即ConcurrentHashMap里面的KEY

fun module(scope:Module.()->Unit):Module{
    val moduleBean = Module()
    scope.invoke(moduleBean)
    return moduleBean
}


open class Module {

    var qualifier : Qualifier<*>? = null
        set(value) {
            field = value
            setParentKey(field)
        }
    private val entry = ConcurrentHashMap<String,Any?>()

    fun getEntry() = entry

    inline fun factory(name:String,single: ()-> Any){
        addSingle(name,single())
    }

    fun addSingle(name: String,any: Any){
        getEntry()[name] = any
    }

    fun get(name: String):Any?{
        return getEntry()[name]
    }

    open fun setParentKey(qualifier: Qualifier<*>?){

    }

    fun getKeys() = entry.keys
}

有了上面這兩個(gè)酌泰,限定和作用域的控制,剩下都是存儲(chǔ)的問(wèn)題匕累,以及處理各種提取內(nèi)容的方法陵刹,以及相應(yīng)的拓展方法,方便取出數(shù)據(jù)欢嘿。

總結(jié)

整體框架使用起來(lái)衰琐,建立在我某一個(gè)項(xiàng)目中也糊,采用注解+反射的方法注入對(duì)象,這個(gè)改善了注入的速度羡宙。目前框架由于我一個(gè)人維護(hù)狸剃,白天要上班,只能晚上寫(xiě)寫(xiě)狗热,能力和時(shí)間都有限钞馁,想法也是有限的,所以歡迎各位Pull Request或者有問(wèn)題留言Issue匿刮,我抽空會(huì)回復(fù)僧凰。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市熟丸,隨后出現(xiàn)的幾起案子训措,更是在濱河造成了極大的恐慌,老刑警劉巖光羞,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绩鸣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡纱兑,警方通過(guò)查閱死者的電腦和手機(jī)呀闻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)萍启,“玉大人总珠,你說(shuō)我怎么就攤上這事】贝浚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵钓瞭,是天一觀的道長(zhǎng)驳遵。 經(jīng)常有香客問(wèn)我,道長(zhǎng)山涡,這世上最難降的妖魔是什么堤结? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮鸭丛,結(jié)果婚禮上竞穷,老公的妹妹穿的比我還像新娘。我一直安慰自己鳞溉,他們只是感情好瘾带,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著熟菲,像睡著了一般看政。 火紅的嫁衣襯著肌膚如雪朴恳。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天允蚣,我揣著相機(jī)與錄音于颖,去河邊找鬼。 笑死嚷兔,一個(gè)胖子當(dāng)著我的面吹牛森渐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冒晰,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼章母,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了翩剪?” 一聲冷哼從身側(cè)響起乳怎,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎前弯,沒(méi)想到半個(gè)月后蚪缀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恕出,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年询枚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖醇疼,靈堂內(nèi)的尸體忽然破棺而出状答,到底是詐尸還是另有隱情,我是刑警寧澤拆宛,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響护桦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜煎娇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一二庵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缓呛,春花似錦催享、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春兰迫,著一層夾襖步出監(jiān)牢的瞬間信殊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工汁果, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涡拘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓据德,卻偏偏與公主長(zhǎng)得像鳄乏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棘利,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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