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 {
}
}
一切都是为了偷懒!!!
网友评论