在 Android 开发中有很多语法糖 , 其中 for Each 可以替代 for 循环 ,简洁 的语法是很常用的
tempList.forEach { Timber.d("print list value =>${it}") }
在使用 for Each 时 , 相信每个开发者都会踩的一个坑就是 for Each 中的 return@forEach 无法直接退出 forEach
tempList.forEach { if (it == ""){ return@forEach } Timber.d("print list value =>${it}") }
先说个最常见的解决方案 , 在外层包一个 run , 然后使用 return@run 退出即可
run{ tempList.forEach { if (it == ""){ return@run } Timber.d("print list value =>${it}") } }
那么为什么 for Each 不能直接退出呢 ? 这就要从 kotlin 中有个非常好用的关键字 inline 说起 , 它可以帮你对做了标记的函数进行内联优化。所谓内联就是,调用的函数在编译的时候会变成代码内嵌的形式
fun test(){ testInline() } private inline fun testInline(){ Timber.d("testInline") } //等于 fun test(){ Timber.d("testInline") }
在 kotlin 中方法也是变量 , 所以这样做的区别在于 , 不实用 inline 每次调用会多创建一个变量 , 在频繁的调用时 , 例如 for 循环中 , 内存的开销会变得很大
这也解释了 for Each 为什么要使用 inline
如果针对其中某个参数不需要 inline 可以使用 no Inline , 效果如下
inline fun test1(first:()->Unit,noinline second:()->Unit){ first() Timber.d("3") second() } fun main(){ test1({ Timber.d("1") },{ Timber.d("2") }) }
等于
fun main(){ Timber.d("1") Timber.d("3") ({ Timber.d("2") }) }
这里面有个坑 , 我们前面提到 , kotlin 中方法也是变量 , 所以在实际使用中 , 就可以加上 noInline 来返回该方法
inline fun test1(first:()->Unit, noinline second:()->Unit): () -> Unit { first() Timber.d("3") return second }
如果不加上 no Inlie
这是因为这时实际编译结果是
fun main(){ Timber.d("1") Timber.d("3") Timber.d("2") second }
可以看到最后突兀的出现一个 second
除了 no Inline 还有个 crossInline , 刚才讲的 noinline 是局部关闭内联优化 , 而这个 crossinline ,是局部加强内联优化
再看一下例子
inline fun test1(first:()->Unit) { first() Timber.d("2") } fun main(){ test1{ Timber.d("1") return } }
当我在使用内联函数时在里面调用了 return , 因为使用内联 , 方法到最后是展开的 , 也就是
fun main(){ Timber.d("1") Timber.d("2") return }
所以 , 他的本质是结束 mai n 函数 , 而不是只结束 test 1 函数
如果将 test 1 中 first 的调用放在主线程中
可以看到系统提示要使用 cross Inline , 在使用之后 , 就会告诉不允许在 mai n 当中这样使用 , main 当中只能 return @ test 1
所以什么时候需要 crossinline?当你需要突破内联函数的「不能间接调用参数」的限制的时候。