kotlin扩展函数(一)

kotlin 用了这么久也一直没有整理过,当想整理的时候又不知道又不知道该整理点啥,于是就从项目中用到最多的整理记录一下.项目中用到的扩展函数比较多,所以先从扩展函数开始,这其中包括Kotlin自带的扩展函数和自己写的扩展函数.

什么是扩展函数?

对于我这样一个Kotlin的初学的菜鸡来说经常会为写不出一些优雅的代码而伤神,经常流连于众大佬的gayhub,感叹大佬用的各种新奇的函数...不管三七二十一先copy过来再说,后来知道这些都是一些扩展函数,是 Kotlin 用来简化一些代码的书写产生的.

在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码。Standard.kt是Kotlin库的一部分,它定义了一些基本函数。 这个源代码文件虽然一共不到50行代码,但是这些函数功能都非常强大,像 let、with、run、apply、also 等函数都在其中.

let

在函数块内可以通过 it 指代该对象。返回值为函数块的最后一行或指定return表达式

inline fun <T, R> T.let(block: (T) -> R): R
  1. 在函数体内使用it替代object对象去访问其公有的属性和方法
object?.let{
    it.todo()
...
}

使用场景

  • 一般写法
fun test() {
   val array = intArrayOf(1, 2, 3, 4, 5)
   array.forEach { println(it) }
   println(array.size)
}
  • let 写法
fun test() {
   val array = intArrayOf(1, 2, 3, 4, 5)
   val result = array.let {
   array.forEach { println(it) }
   it.size
   }
   println(result)
}

输出 1 2 3 4 5 5

  1. 当object不为null的条件下,才会去执行let函数体
object?.let{
    it.todo()
}

使用场景

  • 一般写法
newsBean?.listed =1
newsBean?.isNotFirst = false
newsBean?.area ="ShangHai"
  • let写法
newsBean?.let {
   it.listed =1
   it.isNotFirst = false
   it.area ="ShangHai"
}

also

also函数let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身,一般可用于多个扩展函数链式调用

inline fun <T> T.also(block: (T) -> Unit): T

let与also比较

  • let写法
fun test() {
   val array = intArrayOf(1, 2, 3, 4, 5)
   val result = array.let {
   array.forEach { println(it) }
   it.size
   }
   println(result) // 打印list数组的大小
}
  • also写法
fun test() {
   val array = intArrayOf(1, 2, 3, 4, 5)
   val result = array.also {
       array.forEach { println(it) }
   }
   println(result) //打印 array数组
}

with

不是以扩展的形式存在的,而是将某对象作为函数的参数,在函数块内可以通过 this 或省略指代该对象。返回值为函数块的最后一行或指定return表达式

inline fun <T, R> with(receiver: T, block: T.() -> R): R

可以看出with函数是接收了两个参数,分别为T类型的对象receiver和一个lambda函数块,所以with函数最原始样子如下:

val result = with(caixukun, {
    println("我是篮球大使$name, 我擅长$sing $dance $rap")
    "follow me"
})

但是由于with函数最后一个参数是一个函数,可以把函数提到圆括号的外部,所以最终with函数的调用形式如下:

val result = with(caixukun) {
    println("我是篮球大使$name, 我擅长$sing $dance $rap")
    "follow me"
}

适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可

  1. 将一个类的属性值赋给另一个新类;RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上
  • 一般写法
override fun onBindViewHolder(holder: ViewHolder, position: Int){
    val item = list(position)
    holder.name.text = "名称:${item.name}"
    holder.interest.text = "兴趣:${item.age}"
}
  • with用法
override fun onBindViewHolder(holder: ViewHolder, position: Int){
   val item = list(position)
    with(item){
        holder.nameView.text = "名称:$name"
        holder.ageView.text = 兴趣:age"
    }
}
  1. with函数在使用的时候确实可以省掉很多重复的代码,还有常用的地方是点击RecyclerView 的item方法跳转到下一级页面要传递好几个参数时就可以使用with 简化.
mAdapter.setOnItemChildClickListener { _, _, position -> // id code name 均为item的属性
    with(mAdapter.data[position]) {
        ARouter.getInstance().build("/xx/XxxActivity")
                .withLong(ID, id)
                .withString(CODE, code)
                .withString(NAME, name)
                .navigation()
    }
}

run

run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理.run函数接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式

inline fun <T, R> T.run(block: T.() -> R): R

用法与let相似,这里只简单的举一个栗子.

  • 一般写法
if (list != null){
    list.forEach { 
        println(it)
    }
}
  • run 写法
list?.run{ //不需判空,内部也不需再用it代替list
   forEach { 
        println(it)
    }
}

apply

apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,apply函数的返回的是传入对象的本身,run函数是以闭包形式返回最后一行代码的值

inline fun <T> T.apply(block: T.() -> Unit): T

1.apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。

举个栗子自定义view的时候对自定义属性的初始化

  • 一般用法
val typedArray = context.obtainStyledAttributes(attribute, R.styleable.ShapeView)
mFillColor = typedArray.getColor(R.styleable.ShapeView_sv_fillColor, 0xFFFFFFFF.toInt())
mStrokeColor = typedArray.getColor(R.styleable.ShapeView_sv_strokeColor, 0)
typedArray.recycle()
  • apply用法
context.obtainStyledAttributes(attribute, R.styleable.ShapeView).apply {
    mFillColor = getColor(R.styleable.ShapeView_sv_fillColor, 0xFFFFFFFF.toInt())
    mStrokeColor = getColor(R.styleable.ShapeView_sv_strokeColor, 0)
    recycle()
}
  1. 动态inflate出一个XML的View的时候需要给View绑定数据也会用到
  • 一般写法
val view = layoutInflater.inflate(R.layout.xx, null)
view.findViewById<TextView>(R.id.xx).text = title
  • apply 写法
val view = layoutInflater.inflate(R.layout.xx, null).apply {
    findViewById<TextView>(R.id.xx).text = title
}

总结

是不是可以优化自己项目中一大波代码了.逼格会不会高一点.一时用一时爽,一直用一直爽.

参考资料Kotlin 标准库

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

推荐阅读更多精彩内容