(譯)使用Kotlin的方式添加Fragment

原文地址:https://medium.com/thoughts-overflow/how-to-add-a-fragment-in-kotlin-way-73203c5a450b

1.png

本文介紹了利用Kotlin擴(kuò)展函數(shù)的特性在Activity中管理Fragment的方式。

以下是正文

本文來源于StackOverflow的一個回答

在開始使用Kotlin的方式添加Fragment之前,我們先重新看一下使用Java的方式

原始的方式:

FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(frameId, fragment);
transaction.commit();

為了避免在每個Activity中重復(fù)這樣模板化的代碼构拳,我們一般在ActivityUtil工具類中實現(xiàn)一個靜態(tài)方法

public static void addFragmentToActivity(FragmentManager manager, Fragment fragment, int frameId) {
    
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.add(frameId, fragment);
    transaction.commit();
    
}

然后我們在Activity中調(diào)用這個靜態(tài)方法

ActivityUtil.addFragmentToActivity(
        getSupportFragmentManager(), fragment, R.id.frag_container);

這樣就完了,毫無新意≡柑現(xiàn)在讓我們?nèi)绾问褂肒otlin兩個步驟把這做的更好女责。

1.消除beginTransaction()和commit()

不知道你曾經(jīng)浪費了多少時間來調(diào)試你的程序榨乎,最后才發(fā)現(xiàn)是在Fragment事務(wù)之后忘記調(diào)用commit方法了丁屎。

為了消除上述代碼鲁沥,我們實現(xiàn)一個FragmentManager擴(kuò)展函數(shù),接收一個Lambda表達(dá)式作為參數(shù)呼股。

我們用到的Kotlin功能的快速介紹

擴(kuò)展函數(shù)可以為已經(jīng)存的類添加新的方法或?qū)傩裕词诡悂碜云渌麕旎蛘逽DK的画恰。在方法內(nèi)我們可以直接訪問該類的public方法和屬性彭谁,并且不需要修飾語就好像方法存在類里面一樣。(注意:實際上擴(kuò)展函數(shù)并沒有修改已經(jīng)存在的類而是創(chuàng)建了一個靜態(tài)方法)

高階函數(shù)是以函數(shù)為參數(shù)或者返回值的函數(shù)允扇,我們可以像傳遞數(shù)據(jù)一樣在函數(shù)中傳入或者返回函數(shù)缠局。

Lambda表達(dá)式接收器(函數(shù)字面量接收器)是上面兩者的結(jié)合——一個以指定接收器的擴(kuò)展函數(shù)為參數(shù)的高階函數(shù)。所以在我們傳遞的Lambda表達(dá)式中我們可以直接訪問接收器的公共方法和屬性考润,就好像在接收器內(nèi)部一樣狭园。

這就是FragmentManager的擴(kuò)展函數(shù),接收一個Lambda表達(dá)式接收器作為參數(shù),FragmentTransaction作為接收器

inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> Unit) {
    val fragmentTransaction = beginTransaction()
    fragmentTransaction.func()
    fragmentTransaction.commit()
}

這里參數(shù)為FragmentTransaction的擴(kuò)展函數(shù),函數(shù)沒有參數(shù)并且返回值為Unit.我們在調(diào)用beginTransaction()之后調(diào)用該函數(shù),最后調(diào)用commit()提交事務(wù).

現(xiàn)在在Activity中添加Fragment我們可以這樣調(diào)用

supportFragmentManager.inTransaction {
    add(R.id.frameLayoutContent, fragment)
}

需要說明的是在Lambda表達(dá)式中我們調(diào)用FragmentTransaction的方法如add或者remove時并沒有使用修飾符,因為這是對FragmentTransaction的擴(kuò)展函數(shù).

使用上面的擴(kuò)展函數(shù),我們在添加或者替換Fragment時就不需要調(diào)用beginTransaction()commit()了.我們甚至可以在inTransaction代碼塊中調(diào)用多個方法,每個方法都運行在Fragment的事務(wù)中.(此處不太確定是所有方法運行在一個事務(wù)中還是每個方法在單獨的事務(wù)中)

supportFragmentManager.inTransaction {
    remove(fragmentA)    
    add(R.id.frameLayoutContent, fragmentB)
}

2017年8月24日更新:Dai評論中建議我們可以完善一下inTransaction,讓lambda表達(dá)式返回FragmentTransaction:

inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) {
    beginTransaction().func().commit()
}

2.使用擴(kuò)展函數(shù)代替ActivityUtil

接下來,我們看一下使用AppCompatActivity的擴(kuò)展函數(shù)比ActivityUtil工具類好在哪里

我們可以實現(xiàn)AppCompatActivity的擴(kuò)展函數(shù)addFragmentreplaceFragment:

fun AppCompatActivity.addFragment(fragment: Fragment, frameId: Int){
    supportFragmentManager.inTransaction { add(frameId, fragment) }
}


fun AppCompatActivity.replaceFragment(fragment: Fragment, frameId: Int) {
    supportFragmentManager.inTransaction{replace(frameId, fragment)}
}

由于這是對AppCompatActivity本身的擴(kuò)展函數(shù),我們可以在函數(shù)內(nèi)部直接訪問supportFragmentManager.

使用上面的擴(kuò)展函數(shù),我們在Activity中添加或者替換Fragment可以一行代碼實現(xiàn),不需要任何修飾符:

addFragment(fragment, R.id.fragment_container)

replaceFragment(fragment, R.id.fragment_container)

這里沒有使用額外的修飾符調(diào)用這些函數(shù),看上去好像Android SDK本身提供了這些函數(shù).

使用Kotlin我們彌補(bǔ)了Android API的不足,并且實現(xiàn)了一種更加簡潔,易讀,不容易出錯的添加Fragment的代碼.

不僅如此,使用Kotlin的擴(kuò)展函數(shù),高階函數(shù),Lambda表達(dá)式接收器可以為你的工程創(chuàng)建一個優(yōu)雅的DSL(領(lǐng)域特定語言).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市糊治,隨后出現(xiàn)的幾起案子唱矛,更是在濱河造成了極大的恐慌,老刑警劉巖井辜,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绎谦,死亡現(xiàn)場離奇詭異,居然都是意外死亡粥脚,警方通過查閱死者的電腦和手機(jī)窃肠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刷允,“玉大人冤留,你說我怎么就攤上這事∈髟睿” “怎么了纤怒?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長破托。 經(jīng)常有香客問我肪跋,道長,這世上最難降的妖魔是什么土砂? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任州既,我火速辦了婚禮谜洽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吴叶。我一直安慰自己阐虚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布蚌卤。 她就那樣靜靜地躺著实束,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逊彭。 梳的紋絲不亂的頭發(fā)上咸灿,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天,我揣著相機(jī)與錄音侮叮,去河邊找鬼避矢。 笑死,一個胖子當(dāng)著我的面吹牛囊榜,可吹牛的內(nèi)容都是我干的审胸。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼卸勺,長吁一口氣:“原來是場噩夢啊……” “哼砂沛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起曙求,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤碍庵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后圆到,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怎抛,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年芽淡,在試婚紗的時候發(fā)現(xiàn)自己被綠了马绝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡挣菲,死狀恐怖富稻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情白胀,我是刑警寧澤椭赋,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站或杠,受9級特大地震影響哪怔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一认境、第九天 我趴在偏房一處隱蔽的房頂上張望胚委。 院中可真熱鬧,春花似錦叉信、人聲如沸亩冬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽硅急。三九已至,卻和暖如春佳遂,著一層夾襖步出監(jiān)牢的瞬間营袜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工讶迁, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留连茧,地道東北人。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓巍糯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親客扎。 傳聞我的和親對象是個殘疾皇子祟峦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,930評論 2 361

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