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

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

1.png

本文介绍了利用Kotlin扩展函数的特性在Activity中管理Fragment的方式。

以下是正文

本文来源于StackOverflow的一个回答

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

原始的方式:

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

为了避免在每个Activity中重复这样模板化的代码,我们一般在ActivityUtil工具类中实现一个静态方法

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

然后我们在Activity中调用这个静态方法

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

这样就完了,毫无新意。现在让我们如何使用Kotlin两个步骤把这做的更好。

1.消除beginTransaction()和commit()

不知道你曾经浪费了多少时间来调试你的程序,最后才发现是在Fragment事务之后忘记调用commit方法了。

为了消除上述代码,我们实现一个FragmentManager扩展函数,接收一个Lambda表达式作为参数。

我们用到的Kotlin功能的快速介绍

扩展函数可以为已经存的类添加新的方法或属性,即使类来自其他库或者SDK的。在方法内我们可以直接访问该类的public方法和属性,并且不需要修饰语就好像方法存在类里面一样。(注意:实际上扩展函数并没有修改已经存在的类而是创建了一个静态方法)

高阶函数是以函数为参数或者返回值的函数,我们可以像传递数据一样在函数中传入或者返回函数。

Lambda表达式接收器(函数字面量接收器)是上面两者的结合——一个以指定接收器的扩展函数为参数的高阶函数。所以在我们传递的Lambda表达式中我们可以直接访问接收器的公共方法和属性,就好像在接收器内部一样。

这就是FragmentManager的扩展函数,接收一个Lambda表达式接收器作为参数,FragmentTransaction作为接收器

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

这里参数为FragmentTransaction的扩展函数,函数没有参数并且返回值为Unit.我们在调用beginTransaction()之后调用该函数,最后调用commit()提交事务.

现在在Activity中添加Fragment我们可以这样调用

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

需要说明的是在Lambda表达式中我们调用FragmentTransaction的方法如add或者remove时并没有使用修饰符,因为这是对FragmentTransaction的扩展函数.

使用上面的扩展函数,我们在添加或者替换Fragment时就不需要调用beginTransaction()commit()了.我们甚至可以在inTransaction代码块中调用多个方法,每个方法都运行在Fragment的事务中.(此处不太确定是所有方法运行在一个事务中还是每个方法在单独的事务中)

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

2017年8月24日更新:Dai评论中建议我们可以完善一下inTransaction,让lambda表达式返回FragmentTransaction:

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

2.使用扩展函数代替ActivityUtil

接下来,我们看一下使用AppCompatActivity的扩展函数比ActivityUtil工具类好在哪里

我们可以实现AppCompatActivity的扩展函数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本身的扩展函数,我们可以在函数内部直接访问supportFragmentManager.

使用上面的扩展函数,我们在Activity中添加或者替换Fragment可以一行代码实现,不需要任何修饰符:

addFragment(fragment, R.id.fragment_container)

replaceFragment(fragment, R.id.fragment_container)

这里没有使用额外的修饰符调用这些函数,看上去好像Android SDK本身提供了这些函数.

使用Kotlin我们弥补了Android API的不足,并且实现了一种更加简洁,易读,不容易出错的添加Fragment的代码.

不仅如此,使用Kotlin的扩展函数,高阶函数,Lambda表达式接收器可以为你的工程创建一个优雅的DSL(领域特定语言).

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容