kotlin lambda

作者: 折剑游侠 | 来源:发表于2020-06-19 14:50 被阅读0次

kotlin中给View设置监听可以这么写

bt.setOnClickListener {
       
}

反编译

((Button)this._$_findCachedViewById(id.bt)).setOnClickListener((OnClickListener)(new OnClickListener() {
  public final void onClick(View it) {

  }
}));

编译器帮我们生成了匿名内部类

反过来,在kotlin中定义单抽象方法接口(SAM),是不能这么写的。

class Example {
    private var listener: Listener? = null

    interface Listener {
        fun call(view: View)
    }

    public fun setListener(listener: Listener) {
        this.listener = listener
    }
}

val example = Example()
example.setListener(object :Example.Listener{
  override fun call(view: View) {

  }
})

改造下

class Example {
    private var callback: ((View) -> Unit)? = null

    public fun setListener(callback: (View) -> Unit) {
        this.callback = callback
    }
}

val example = Example()
example.setListener {

}

重点(View) -> Unit

反编译成JAVA

private Function1 callback;

Function1

/** A function that takes 0 arguments. */
public interface Function0<out R> : Function<R> {
    /** Invokes the function. */
    public operator fun invoke(): R
}
/** A function that takes 1 argument. */
public interface Function1<in P1, out R> : Function<R> {
    /** Invokes the function with the specified argument. */
    public operator fun invoke(p1: P1): R
}
/** A function that takes 2 arguments. */
public interface Function2<in P1, in P2, out R> : Function<R> {
    /** Invokes the function with the specified arguments. */
    public operator fun invoke(p1: P1, p2: P2): R
}
......

官方定义的接口,最多支持22个参数Function22。也就是说lambda最终会编译成对应参数数量的Function,其抽象方法invoke()供外部调用。

接下来定义几个lambda

private lateinit var call: () -> Unit
private lateinit var call1: (Int) -> Unit
private lateinit var call2: (Int, String) -> Unit
private lateinit var call3: (Int, String, Double) -> Unit

反编译

public final class LambdaKt {
   private static Function0 call;
   private static Function1 call1;
   private static Function2 call2;
   private static Function3 call3;
}

解释下,以call1为例,接收一个Int类型的参数,返回值为空Unit。

举个例子

fun View.setListener(call: (View) -> Unit) {
    this.setOnClickListener {
        call(this)
    }
}

fun View.setListener(call: (View, Int) -> Unit) {
    this.setOnClickListener {
        call(this, 0)
    }
}

fun View.setListener(call: (View, Int, String) -> Unit) {
    this.setOnClickListener {
        call(this, 0, "")
    }
}

调用处

bt.setListener { view ->

}

bt.setListener { view, position ->

}

bt.setListener { view, position, title ->

}

给view添加扩展方法setListener,bt被点击的时回调到lambda,这里只做演示,无实际意义。

单参数可以省略,lambda内默认it指向参数
bt.setListener {it

}
用不到的参数用下划线代替
bt.setListener { view, _ ->

}
带接收者的lambda
fun View.setListener(call: View.() -> Unit) {
    this.setOnClickListener {
        call()
    }
}
写法类似扩展方法View.() -> Unit
bt.setListener {this
  //内部this指向调用者
}
在 Kotlin 中有⼀个约定:如果函数的最后⼀个参数是函数,那么作为相应参数传⼊的 lambda 表达式可以放在圆括号之外
fun View.setListener(title: String, call: () -> Unit) {
    this.setOnClickListener {
        call()
    }
}

bt.setListener("") {

}
实战操作一下权限处理框架AndPermission
inline fun Activity.andPermission(permission: String, block: PermissionRequest.() -> Unit) =
        AndPermission
                .with(this)
                .runtime()
                .permission(permission)
                .apply {
                    block()
                }
                .start()

Activity中调用

andPermission(Permission.WRITE_EXTERNAL_STORAGE){
  onGranted {
                
  }
  onDenied {
                
  }
}

一切都是为了偷懒!!!

相关文章

网友评论

    本文标题:kotlin lambda

    本文链接:https://www.haomeiwen.com/subject/euqvxktx.html