上一篇介绍了inline,这篇介绍下noinline,noinline需要在inline函数中才能用
1.noinline的作用
区部取消内联作用,举个例子
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainInline({ print("你好") }) { print("再见") }
}
inline fun mainInline(func1: () -> Unit, noinline func2: () -> Unit) {
func1()
func2()
}
}
mainInline是一个内联函数,有2个函数类型参数,一个内联,一个不内联(noinline)
看下调用处字节码
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(1300009);
Function0 func2$iv = (Function0)null.INSTANCE;
int $i$f$mainInline = false;
int var5 = false;
String var6 = "你好"; // 1
boolean var7 = false; // 2
System.out.print(var6); // 3
func2$iv.invoke(); // 4
}
可以看到1~3步是func1函数体直接复制到了调用处,参与了内联
第4步,依然是调用func2.invoke(),没有将函数体复制过来,跳过了内联
2.noinline的使用场景
简单来说就是不想参与内联的时候就可以加上noinline,或者是这样一个场景
inline fun mainInline(func1: () -> Unit, noinline func2: () -> Unit): () -> Unit {
func1()
func2()
return func2
}
修改了一下最开始的mainInline函数,增加了返回值() -> Unit,我们需要一个函数返回
1.如果我们 return func1 编译器会报错,因为func1参与了内联,在调用处是讲函数体直接复制过去,他无法被当成一个对象去返回(inline那篇有介绍函数类型参数的实现原理,kotlin实际创建了函数类型对象)
2.我们return func2是可以的,因为跳过了内联,他依然能被当成函数对象返回。
小结:如果我们想继续将函数类型参数当做函数对象使用,就可以添加noinline跳过内联