Kotlin:Standard.kt标准库常用API总结

在这里插入图片描述

在 Kotlin 源码的Standard.kt标准库中提供了一些便捷的内置高阶函数( letalsowithrunapply ),可以帮助我们写出更简洁优雅的 Kotlin 代码,提高开发效率。但前提是先要对高阶函数有所了解。

// 比如这样初始化一个User
// 这样的代码是不是简洁优雅,我是比较喜欢这种风格的
val user = User().apply {
    this.name = "kotlin"
    this.age = 18
    this.isMale = true
}
1、apply
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}
  • 传递this作为block函数参数(调用时可以省略),且apply函数的返回值是调用者本身
  • 实际应用:Fragment的newInstance()方法传递参数时
fun newInstance(param: String) {
    return DemoFragment().apply {
        arguments = Bundle().apply {
            putString(ARG_PARAM, param)
        }
    }
}

2、also
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}
  • 传递it作为block函数参数(调用时不可以省略),且also函数的返回值是调用者本身
  • 实际应用:applyalso之间可以相互替换,只是参数不同而已
3、let
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
  • 传递it作为block函数参数,且let函数的返回值是由block函数决定的
  • 实际应用:在Activity或Fragment传参时
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    arguments?.let {
        param = it.getString(ARG_PARAM)
    }
}
4、with
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}
  • 需要传递两个参数,需要操作的对象和block函数
  • 传递this作为block函数参数,且with函数的返回值是由block函数决定的
  • 实际应用:
with(recyclerView) {
    layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
    adapter = mAdapter
}
5、run
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
  • 第一个run就是一般的高阶函数,为了能用Lambda表示,实际应用比较少
  • 传递this作为block函数参数,且run函数的返回值是由block函数决定的
  • 实际应用:runlet之间可以互相替换,只是传递参数不同

但是大家在平时实际开发中是不是有这种感觉,这么多内置函数我该选哪一个呢?反正我在刚开始接触标准库时,我是这种感觉,一脸懵逼。。。
但在后来开发中,慢慢熟悉过后,发现其实也有规律可循,可参考顶图。

  • 如果需要返回自身调用者本身(即return this),可以选择 apply also
  • 如果需要传递this作为参数,可以选择 apply run with
  • 如果需要传递it作为参数,可以选择 let also
  • 如果返回值需要函数决定(即return block()),可以选择 run with let
扩展:利用标准函数库实现自己的高阶函数
/**
 * 使用TypedArray可以不用自己recycle
 */
inline fun <R> TypedArray.use(block: (TypedArray) -> R): R {
    return block(this).also {
        recycle()
    }
}

/**
 * 使用Bitmap可以不用自己recycle
 */
inline fun <R> Bitmap.use(block: (Bitmap) -> R): R {
    return block(this).also {
        recycle()
    }
}
参考

https://www.jianshu.com/p/301ca23f6055

https://juejin.im/post/6844903608161419277

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值