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.let(block: (T) -> R): R
- 在函数体内使用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
- 当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.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
可以看出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"
}
适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可
- 将一个类的属性值赋给另一个新类;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"
}
}
- 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.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.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()
}
- 动态inflate出一个XML的View的时候需要给View绑定数据也会用到
- 一般写法
val view = layoutInflater.inflate(R.layout.xx, null)
view.findViewById(R.id.xx).text = title
- apply 写法
val view = layoutInflater.inflate(R.layout.xx, null).apply {
findViewById(R.id.xx).text = title
}
总结
是不是可以优化自己项目中一大波代码了.逼格会不会高一点.一时用一时爽,一直用一直爽.
参考资料Kotlin 标准库