ITPub博客

首页 > 移动开发 > ANDROID > 从forEach理解一下kotlin的inline

从forEach理解一下kotlin的inline

原创 ANDROID 作者:山有木xi 时间:2024-02-26 11:37:22 0 删除 编辑

在 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?当你需要突破内联函数的「不能间接调用参数」的限制的时候。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917874/viewspace-3007312/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle OCA(Java),IBM高级工程师认证,中国软件行业人才(高级c语言),高级Android工程师,对数据库并发与性能调优也有一定了解

注册时间:2019-04-25

  • 博文量
    147
  • 访问量
    390782