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 {
}
}
一切都是爲了偷懶!!!