kotlin lambda

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 {
                
  }
}

一切都是爲了偷懶!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章