Kotlin Lambda and Extension
Extension Function(扩展函数)
Extension Function 能在已经存在的类中添加新的方法或者属性,即使这些类来自库或者SDK中。在函数内部,我们可以访问类的公共函数和属性而不需要任何限定符,就好像这个函数就在这个类的内部一样。(注意:从技术上将,它并没有修改现有类,只是在声明的类中创建了static public final函数)
举个栗子
object KotMain {
@JvmStatic
fun main(args: Array<String>) {
val person = "snoopy"
person.say("hello")
}
fun String.say(sth: String) {
println("$this say $sth")
}
}
反编译后我们可以看到生成的java代码
public final class KotMain {
public static final KotMain INSTANCE;
public static final void main(@NotNull String[] args) {
Instrinsics.checkParameterIsNotNull(args, "args");
String person = "snoopy";
INSTANCE.say(person, "hello");
}
public final void say(@NotNull String $this$say, @NotNull String sth) {
Instrinsics.checkParameterIsNotNull($this$say, "$this$say");
Instrinsics.checkParameterIsNotNull(sth, "sth");
String var3 = $this$say + ' ' + sth;
System.out.println(var3);
}
}
可以看到只是增加了一个final方法。
接下来看看如何在Android项目中运用它
可以生成任何Android View实例的函数
inline fun<reified V: View> v(context: Context, init: V.() -> Unit): V{ val instance = V::class.java.getConstructor(context::class.java) val view = instace.newInstance(context) view.init() return view }
dp-px拓展
fun View.dp2px(dp: Float) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.resource.displayMetrics) }
添加fragment
inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> Unit) { val fragmentTransaction = begainTransaction() fragmentTransaction.func() fragmentTransaction.commit() } //使用 supportFragmentManager.inTransaction { add(R.id.container, fragment) //other operation }
High Order Function
High Order Function 在 kotlin 的官网中有很明确的解释:
Higher-Order Functions
A higher-order function is a function that takes functions as parameters, or returns a function.
高阶函数是将函数作为参数或返回函数的函数。
High Order Function 中函数作为参数的情况
inline fun test1(func:Int.() -> Unit) {
func(1)
}
inline fun Int.test2(func:Int.() -> Unit) {
func()
}
public final void test1(int $this$test1, Function1 call) {
call.invoke($this$test)
}
public final void test2(Function1 call) {
call.invoke(1)
}
Lambda with Receiver
什么是Lambda with Receiver? Extension Function + Lambda = Lambda with Receiver,它允许你在没有任何限定符的情况下调用lambda中对象的方法。
inline function
在kotlin中,函数是一等公民,所以我们可以传递函数或者像其它普通类型一样返回它们。然而,这些函数在运行时可能会产生一些性能上的问题,它们作为对象存储造成了额外的内存开销,这时候就轮到inline登场了,在一些使用High Order Function的场景中,我们一般用inline(内联)去修饰它,这样可以减少调用开销。我们依然从源码出发,通过反编译,看看使用High Order Function编译成Java是什么样子的。
object KotMain {
@JvmStatic
fun main(args: Array<String>) {
noInline {
println("调用中")
}
inlineFunc {
println("调用中")
}
}
fun noInline(call: ()->Unit) {
println("调用前")
call()
println("调用后")
}
inline fun inlineFunc(call: ()->Unit) {
println("调用前")
call()
println("调用后")
}
}
再来看看java代码
public final class KotMain {
public static final KotlinMain INSTANCE;
public static final void main(String[] args) {
//no inline
INSTANCE.noInline(new Function() {
@Override
public void invoke() {
System.out.println("调用中");
}
})
//inline
System.out.println("调用前");
System.out.println("调用中");
System.out.println("调用后");
}
public final void noInline(Function func) {
println("调用前");
func.invoke()
println("调用后");
}
}
大家可以非常直观的看到结论,不使用内联修饰符,每次调用这个函数都会初始化一个Function实例,显然会造成内存开销,而使用内联修饰符,不会创建Function实例,而会将回调函数内部的代码复制到call site中。
参考
kotlin-extension function
Kotlin里的Extension Functions实现原理分析
How to Add a Fragment the Kotlin way