Kotlin -- 委托


在委托模式中帮孔,有兩個(gè)對(duì)象參與處理同一個(gè)請(qǐng)求碉就,接受請(qǐng)求的對(duì)象將請(qǐng)求委托給另一個(gè)對(duì)象來(lái)處理钳吟。


類委托


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val b = Bean("hello world")
        Delegation(b).delegate()
    }

}

interface IDelegateListener {
    fun delegate()
}

class Bean(val s: String) : IDelegateListener {
    override fun delegate() {
        println("bean ----> $s")
    }
}

class Delegation(delegateListener: IDelegateListener) : IDelegateListener by delegateListener


運(yùn)行結(jié)果

由輸出結(jié)果可以看到:Delegation類并沒有實(shí)現(xiàn) IDelegateListener 中的 delegate() 方法手素,而是通過(guò)by這個(gè)關(guān)鍵字滴铅,將本應(yīng)該實(shí)現(xiàn)的方法委托給了Bean,由Bean來(lái)實(shí)現(xiàn)方法


委托屬性

定義一個(gè)委托屬性的語(yǔ)法是: val/var <property name>: <Type> by <expression> ,by后面的就是屬性的委托戳葵。委托屬性不需要實(shí)現(xiàn)接口,只需要用operator修飾的 setValue() getValue函數(shù)汉匙。如果是val屬性 則不用提供setValue()

class MainActivity : AppCompatActivity() {

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

        val bean = Bean()
        println("bean ---> ${bean.string}")
        bean.string="2"
        println("bean ---> ${bean.string}")
    }

}


class Bean {
    var string: String by Delegator()
}

class Delegator {
    var temp = "1"

    operator fun getValue(ref: Any?, p: KProperty<*>): String {
        return "Delegator --> ${p.name} --> $temp"
    }

    operator fun setValue(ref: Any?, p: KProperty<*>, value: String) {
        temp = value
    }

}


運(yùn)行結(jié)果

參數(shù)說(shuō)明:

  • ref 屬性擁有者
  • p 屬性的描述
  • value 屬性的值

標(biāo)準(zhǔn)委托

延遲屬性 lazy

通過(guò)lazy可以定義一個(gè)懶加載屬性拱烁,只有val類型的屬性才能延遲初始化,且只初始化一次噩翠,lazy()是接受一個(gè) lambda 并返回一個(gè) Lazy <T> 實(shí)例的函數(shù)戏自,返回的實(shí)例可以作為實(shí)現(xiàn)延遲屬性的委托: 第一次調(diào)用 get() 會(huì)執(zhí)行已傳遞給 lazy() 的 lambda 表達(dá)式并記錄結(jié)果, 后續(xù)調(diào)用 get() 只是返回記錄的結(jié)果伤锚。

class MainActivity : AppCompatActivity() {

    val lazyValue:String by lazy {
        println("1 ---->賦值")
        "lazy"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        println("2 ---->$lazyValue")
        println("3 ---->$lazyValue")
    }

}

運(yùn)行結(jié)果

可以從運(yùn)行結(jié)果看出:只有在第一次使用的時(shí)候才將"lazy"賦值

默認(rèn)情況下擅笔,對(duì)于 lazy屬性的求值是同步鎖的(synchronized):該值只在一個(gè)線程中計(jì)算,并且所有線程會(huì)看到相同的值屯援。如果初始化委托的同步鎖不是必需的猛们,這樣多個(gè)線程可以同時(shí)執(zhí)行,那么將 LazyThreadSafetyMode.PUBLICATION作為參數(shù)傳遞給 lazy() 函數(shù)狞洋。 而如果你確定初始化將總是發(fā)生在單個(gè)線程弯淘,那么你可以使用 LazyThreadSafetyMode.NONE 模式, 它不會(huì)有任何線程安全的保證和相關(guān)的開銷吉懊。


可觀察屬性 Observable

Delegates.observable()接受兩個(gè)參數(shù):初始值和修改時(shí)處理程序(handler)庐橙。 每當(dāng)我們給屬性賦值時(shí)會(huì)調(diào)用該處理程序(在賦值執(zhí)行)假勿。它有三個(gè)參數(shù):被賦值的屬性、舊值和新值

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val observableUse = ObservableUse()
        observableUse.s = "1"
        observableUse.i = "2"
        println("observable ----> ${observableUse.s}")
        println("observable ----> ${observableUse.i}")
    }

}



class ObservableUse {

    var s: String by Delegates.observable("0") { property, oldValue, newValue ->
        println("observable ----> $property,$oldValue,$newValue")
    }

    var i: String by Delegates.vetoable("3") { property, oldValue, newValue ->
        newValue.length > oldValue.length
    }

}


運(yùn)行結(jié)果

通過(guò)可觀察屬性态鳖,就可以實(shí)現(xiàn)一些觀察者模式的方法转培,如果你想能夠截獲一個(gè)賦值并“否決”它,就使用 vetoable() 取代 observable()郁惜。 在屬性被賦新值生效之前會(huì)調(diào)用傳遞給 vetoable 的處理程序堡距。


實(shí)際應(yīng)用場(chǎng)景

通過(guò)委托,我們可以封裝一些工具類兆蕉,例如 Intent 取值 SharedPrefrences 取值等:

/**
 *  kotlin 委托傳值工具
 */
class ExtraDelegator<out T>(private val extraKey:String , private val defaultValue:T) {
    private var extra: T? = null
    operator fun getValue(thisRef: AppCompatActivity, property: KProperty<*>): T {
        extra = getExtra(extra, extraKey, thisRef)
        return extra ?: defaultValue
    }

    operator fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        extra = getExtra(extra, extraKey, thisRef)
        return extra ?: defaultValue
    }

    fun <T> extraDelegate(extra: String, default: T) = ExtrasDelegate(extra, default)

    fun extraDelegate(extra: String) = extraDelegate(extra, null)

    @Suppress("UNCHECKED_CAST")
    private fun <T> getExtra(oldExtra: T?, extraKey: String, thisRef: AppCompatActivity): T? =
            oldExtra ?: thisRef.intent?.extras?.get(extraKey) as T?

    @Suppress("UNCHECKED_CAST")
    private fun <T> getExtra(oldExtra: T?, extraKey: String, thisRef: Fragment): T? =
            oldExtra ?: thisRef.arguments?.get(extraKey) as T?
}

使用:


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 傳值
        content_tv.setOnClickListener {
            val intent = Intent(this@MainActivity, TestActivity::class.java)
            intent.putExtra("string","value")
            startActivity(intent)
        }
    }

}


class TestActivity:AppCompatActivity(){
    val string:String? by extraDelegate("string") // 通過(guò)委托接收
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
        println("TestActivity ------> $string")
    }
}


打印結(jié)果

結(jié)語(yǔ)

通過(guò)委托和擴(kuò)展函數(shù)可以封裝很多有趣的工具類羽戒,從Java 過(guò)度到Kotlin 的感覺就好像從 Eclipse 過(guò)渡到 Android Studio 一開始覺得麻煩,但是用一用就覺得:誒虎韵,還可以易稠,到現(xiàn)在已經(jīng)基本不想再用Java寫了 , 對(duì)于新的東西包蓝,還是要去敢于嘗試驶社。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市测萎,隨后出現(xiàn)的幾起案子亡电,更是在濱河造成了極大的恐慌,老刑警劉巖硅瞧,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件份乒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡腕唧,警方通過(guò)查閱死者的電腦和手機(jī)或辖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)枣接,“玉大人颂暇,你說(shuō)我怎么就攤上這事〉蹋” “怎么了耳鸯?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)榆骚。 經(jīng)常有香客問我片拍,道長(zhǎng),這世上最難降的妖魔是什么妓肢? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮苫纤,結(jié)果婚禮上碉钠,老公的妹妹穿的比我還像新娘纲缓。我一直安慰自己,他們只是感情好喊废,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布祝高。 她就那樣靜靜地躺著,像睡著了一般污筷。 火紅的嫁衣襯著肌膚如雪工闺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天瓣蛀,我揣著相機(jī)與錄音陆蟆,去河邊找鬼。 笑死惋增,一個(gè)胖子當(dāng)著我的面吹牛叠殷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诈皿,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼林束,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了稽亏?” 一聲冷哼從身側(cè)響起壶冒,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎截歉,沒想到半個(gè)月后胖腾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怎披,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年胸嘁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凉逛。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡性宏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出状飞,到底是詐尸還是另有隱情毫胜,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布诬辈,位于F島的核電站酵使,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏焙糟。R本人自食惡果不足惜口渔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望穿撮。 院中可真熱鬧缺脉,春花似錦痪欲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至礁扮,卻和暖如春知举,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背太伊。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工雇锡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人倦畅。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓遮糖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親叠赐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子欲账,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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

  • 1 類委托 Derived 的超類型列表中的 by句表示b 將會(huì)在 Derived 中內(nèi)部存儲(chǔ)。 并且編譯器將成轉(zhuǎn)...
    NiceDream閱讀 1,540評(píng)論 1 3
  • 本文是在學(xué)習(xí)和使用kotlin時(shí)的一些總結(jié)與體會(huì)芭概,一些代碼示例來(lái)自于網(wǎng)絡(luò)或Kotlin官方文檔赛不,持續(xù)更新... 對(duì)...
    竹塵居士閱讀 3,298評(píng)論 0 8
  • 前言 人生苦多,快來(lái) Kotlin 罢洲,快速學(xué)習(xí)Kotlin踢故! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,217評(píng)論 9 118
  • 2018年第3周檢視惹苗,日期:01/15/2018-01/21/2018殿较。天氣總況:溫暖。心情概況:不錯(cuò)桩蓉。 上周調(diào)整...
    老米子007er閱讀 259評(píng)論 4 8
  • 你認(rèn)為院究,什么才是有趣的人洽瞬? 最近都在宣揚(yáng)要尋找有趣的靈魂,說(shuō)只有遇到這樣的人业汰,生活才會(huì)更加豐富多彩伙窃,人...
    372a44c29777閱讀 673評(píng)論 0 1