Kotlin 使用高階函數(shù)實(shí)現(xiàn)回調(diào)

lambda 和 高階函數(shù)

之前學(xué)習(xí)了 lambda 和高階函數(shù),然后在 android 開發(fā)中對 onClick 事件進(jìn)行監(jiān)聽是一個很常用的功能徽鼎,kotlin 的常規(guī)實(shí)現(xiàn)如下:

    rootView.setOnClickListener { view ->
        println("點(diǎn)擊了這個ID=${view.id}的view")
    }

然后在開發(fā)中不可避免的我們也要寫一些自定義監(jiān)聽之類的代碼胚嘲。這個時候如果還用 java 的思想去實(shí)現(xiàn)的話就有點(diǎn)舍近求遠(yuǎn)了。

java 思想實(shí)現(xiàn)

在 java 中我們一般的做法是這樣的

  • 定義一個接口
  • 定義一個接口類型變量
  • 定義一個 set 方法
  • 調(diào)用 set 方法設(shè)置接口的實(shí)現(xiàn)類

用 kotlin 實(shí)現(xiàn)就是如下

class MyView{
    //定義一個接口
    interface IOnLabelCheckedListener {
        fun onLabelCheck(label: String)
    }
    //定義一個接口類型變量
    private lateinit var onLabelChecked: IOnLabelCheckedListener

    private fun initView(context: Context) {
        view.setOnCheckedChangeListener { radioGroup, i ->
            if (checkListener()) {
                //接口調(diào)用
                onLabelChecked.onLabelCheck(radioGroup.findViewById<RadioButton>(i).text.toString())
            }
        }
    }
    private fun checkListener() = ::onLabelChecked.isInitialized
    //定義一個 set 方法
    fun setOnLabelCheckedListener(e: IOnLabelCheckedListener) {
        this.onLabelChecked = e
    }
}

      // 調(diào)用set方法拘悦,通過匿名內(nèi)部類實(shí)現(xiàn)
        MyView.setOnLabelCheckedListener(object : LabelBarView.IOnLabelCheckedListener {
            override fun onLabelCheck(label: String) {

            }
        })

Java 實(shí)現(xiàn)的問題

當(dāng)然是太復(fù)雜了锋爪。同時可以稍微考慮一下性能的問題婆翔。而且最初的時候這樣寫一時搞不明白為什么 MyView.setOnLabelCheckedListener 方法內(nèi)部不能傳入 lambda 表達(dá)式水泉,lambda 表達(dá)式的存在不就是為了替代匿名內(nèi)部類嘛善涨。而且如果這個接口定義的是一個 java 類型的接口就是可以用 lambda 表達(dá)式的窒盐。這是為什么?最后猜想是因為 kotlin 在和 java 互相調(diào)用的時候中間又包裹了一層钢拧,而我們直接使用 kotlin 來定義這個接口不存在中間這一層就而我們定義的 set 方法又不是一個高階函數(shù)蟹漓,當(dāng)然不能使用 lambda 表達(dá)式。(其實(shí)這里參考 Java 的 lambda 的實(shí)現(xiàn)與匿名內(nèi)部類的區(qū)別也可以明白—— lambda 的內(nèi)部實(shí)現(xiàn)并不是匿名內(nèi)部類)

下面就用 kotlin 的思想來實(shí)現(xiàn)回調(diào)

使用高階函數(shù)來實(shí)現(xiàn)

kotlin 和 java 有一個重要的不同就是函數(shù)式編程娶靡。在函數(shù)式編程的思想中函數(shù)式一等公民牧牢,在使用 kotlin 時我們要多利用這種思維來思考問題看锉。Kotlin 中提供了高階函數(shù)姿锭,它可以直接使用一個函數(shù)來作為返回值,對于習(xí)慣于 java 來編程的我來說剛開始理解起來有些困難伯铣,下面我把我一步一步的實(shí)現(xiàn)一個高階函數(shù)的思路寫下呻此,希望對大家有所幫助。

首先腔寡,能想到的就是函數(shù)傳遞焚鲜,要用 lambda 來替代掉匿名內(nèi)部類可以這樣來實(shí)現(xiàn)

//從最基礎(chǔ)的開始做,把匿名內(nèi)部類通過 lambda 實(shí)現(xiàn)
MyView.setOnLabelCheckedListener(object : MyView.IOnLabelCheckedListener {
        override fun onLabelCheck(label: String) {
          println(label)
        }
})
// 首先 MyView.IOnLabelCheckedListener 中只有一個方法 onLabelCheck(label: String)
// 因此可以寫出 lambda 表達(dá)式如下
var lam: (String) -> Unit = { label -> println(label) }

然后放前,需要把寫好的 lambda 傳遞進(jìn)去忿磅,這個時候就要求 setOnLabelCheckedListener 方法是一個高階函數(shù)

    // 這里接收一個 上面我們改造好的表達(dá)式 lam ,它內(nèi)部實(shí)現(xiàn)應(yīng)該是把 e 賦值給當(dāng)前類的一個對象
    fun setOnLabelCheckedListener(e: (String) -> Unit) {
       this.lisenter = e
    }
  
    //顯然 lisenter 就應(yīng)該是這樣的
    lateinit var linsnter: (String) -> Unit

最后使用 linsnter 進(jìn)行回調(diào)

    private fun initView(context: Context) {
       view.setOnCheckedChangeListener { radioGroup, i ->
            linsnter(radioGroup.findViewById<RadioButton>(i).text.toString())
        }
    }

最終代碼結(jié)果:

class MyView{
  lateinit var linsnter: (String) -> Unit

  private fun initView(context: Context) {
       view.setOnCheckedChangeListener { radioGroup, i ->
           if (checkListener())
            linsnter(radioGroup.findViewById<RadioButton>(i).text.toString())
        }
  }
  private fun checkListener() = ::linsnter.isInitialized
  fun setOnLabelCheckedListener(e: (String) -> Unit) {  
    this.lisenter = e
  }
}
    // 調(diào)用時將變量 lam 省略,直接使用一個表達(dá)式
    view.setOnLabelCheckedListener { label ->
        println(label)
    }

最終的代碼和之前的代碼有兩個最大的不同凭语,一是沒有了接口定義葱她,二是沒有了匿名內(nèi)部類。

這樣的好處是顯而易見的似扔,因為少了匿名內(nèi)部類的使用吨些,在程序運(yùn)行過程中是提高了性能的。

以上就是在 Kotlin 中使用高階函數(shù)來替代傳統(tǒng)的回調(diào)函數(shù)的方法炒辉。不對之處還請指正豪墅。

參考文章
高階函數(shù)與 lambda 表達(dá)式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市黔寇,隨后出現(xiàn)的幾起案子偶器,更是在濱河造成了極大的恐慌,老刑警劉巖缝裤,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屏轰,死亡現(xiàn)場離奇詭異,居然都是意外死亡倘是,警方通過查閱死者的電腦和手機(jī)亭枷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搀崭,“玉大人叨粘,你說我怎么就攤上這事猾编。” “怎么了升敲?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵答倡,是天一觀的道長。 經(jīng)常有香客問我驴党,道長瘪撇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任港庄,我火速辦了婚禮倔既,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鹏氧。我一直安慰自己渤涌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布把还。 她就那樣靜靜地躺著实蓬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吊履。 梳的紋絲不亂的頭發(fā)上安皱,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音艇炎,去河邊找鬼酌伊。 笑死,一個胖子當(dāng)著我的面吹牛冕臭,可吹牛的內(nèi)容都是我干的腺晾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼辜贵,長吁一口氣:“原來是場噩夢啊……” “哼悯蝉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起托慨,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鼻由,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后厚棵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蕉世,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年婆硬,在試婚紗的時候發(fā)現(xiàn)自己被綠了狠轻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡彬犯,死狀恐怖向楼,靈堂內(nèi)的尸體忽然破棺而出查吊,到底是詐尸還是另有隱情,我是刑警寧澤湖蜕,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布逻卖,位于F島的核電站,受9級特大地震影響昭抒,放射性物質(zhì)發(fā)生泄漏评也。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一灭返、第九天 我趴在偏房一處隱蔽的房頂上張望盗迟。 院中可真熱鬧,春花似錦婆殿、人聲如沸诈乒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喂饥,卻和暖如春消约,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背员帮。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工或粮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捞高。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓氯材,卻偏偏與公主長得像,于是被迫代替她去往敵國和親硝岗。 傳聞我的和親對象是個殘疾皇子氢哮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

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

  • 前言 人生苦多,快來 Kotlin 型檀,快速學(xué)習(xí)Kotlin冗尤! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,211評論 9 118
  • 原文鏈接:https://github.com/EasyKotlin 值就是函數(shù)胀溺,函數(shù)就是值裂七。所有函數(shù)都消費(fèi)函數(shù),...
    JackChen1024閱讀 5,978評論 1 17
  • 寫在開頭:本人打算開始寫一個Kotlin系列的教程仓坞,一是使自己記憶和理解的更加深刻背零,二是可以分享給同樣想學(xué)習(xí)Kot...
    胡奚冰閱讀 1,306評論 1 5
  • 不重要的廢話 前段時間看了一遍《Programming Kotlin》,主要目的是想提高自己的英文閱讀能力无埃,能力提...
    珞澤珈群閱讀 3,362評論 1 7
  • 恩徙瓶,今天初九蝎困,恩,純粹是去走人家的倍啥,心里或許還有想著去看看曾經(jīng)的小學(xué)初中同學(xué)禾乘,恩,然后虽缕,就很湊巧很湊巧的始藕,遇到了初...
    陽光下的野草閱讀 245評論 0 0