有点晕,inline, crossinline,noinline小计

inline 主要用于展开铺平函数,用于高频访问但是代码不是很多的方法,减少函数对象的定义

fun <T> List<T>.normalForeach(action:(T)->Unit){
    for(item in this){
        action(item)
    }
}

inline fun <T> List<T>.inlinedForeach(action: (T) -> Unit){
    for(item in this){
        action(item)
    }
}

inline就好像把函数内部的代码拷贝一份到调用的地方,减少了函数对象的中间产生。

带来的变化是,可以非本地的返回

fun main(){

    val list = (1..100).toList()
        
        list.normalForeach { 
            println(it)
            return@normalForeach
        }
        
        
        list.inlinedForeach { 
            println(it)
            return
        }

}

普通的函数只能返回 return@normalForeach

内敛函数,因为相当于被拷贝过来了,可以直接返回到main,

另外内敛带来的变化还有

fun main(){

    val list = (1..100).toList()
    CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        list.normalForeach {
            println(it)
            delay(1000) //错误!非内敛,无scope环境
            return@normalForeach
        }

        list.inlinedForeach {
            println(it)
            delay(1000)
            return@launch
        }

    }
}

我们启动了一个协程,但是在normalForeach的lambda中无法使用delay,因为这里其实是一个函数对象,会指向到另外一个函数方法,没有协程的上下文环境,但是内敛函数就不一样了,他相当于是把lambda中的内容拷贝平铺过来了,所以,在inlinedForeach中可以使用协程的上下文环境,delay可以执行。

但是当一个函数被声明为内敛函数的时候,只能直接的运行函数参数,或者在另外一个内敛函数中运行函数参数,

inline fun <T> List<T>.inlinedForeach(action: (T) -> Unit){
    for(item in this){
        action(item) //直接运行方法参数
        kotlin.run {
            action(item) //或者在另外一个内敛函数中运行

        }
        Thread{
            action(item) //报错!不可以跨scope或者context
        }
    }
}

那如果我们必须要参数中的函数可以切换调用呢?

那我们需要在函数参数上crossinline关键字,允许函数被跨上下文调用

inline fun <T> List<T>.inlinedForeach(crossinline action: (T) -> Unit){
    for(item in this){
        action(item) //直接运行方法参数
        kotlin.run {
            action(item) //或者在另外一个内敛函数中运行

        }
        Thread{
            action(item) //因为crossinline关键字,不报错了
        }
    }
}

这样,就可以在Thread中调用action了,但是因为函数参数被声明了crossinlne,原本的非本地返回就不可以用了

所以要不要非本地返回和跨上下文调用,只能二选一

另外,当把一个函数声明为inline的时候,他的lambda参数也是inline的,所以无法通过函数地址引用的方式来调用

但是我们需要再inline声明的函数参数中,通过地址的方式来引用的话,就要noinline来声明


inline fun <T> List<T>.inlinedForeach(
    crossinline action: (T) -> Unit,
    noinline onError: (Exception) -> Unit
) {
    try {
        for (item in this) {
            action(item) //直接运行方法参数
            kotlin.run {
                action(item) //或者在另外一个内敛函数中运行

            }
            Thread {
                action(item) //因为crossinline关键字,不报错了
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
        handleError(e,onError)
    }

}

fun handleError(exception: java.lang.Exception,onError: (Exception) -> Unit) {

    println("handle ")
    onError(exception)
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值