原文在 https://github.com/Zhuinden/guide-to-kotlin
lambda types, tailing lambdas
class MyAdapter(
private var items: List<Item>,
private val clickListener: (Item) -> Unit
): RecyclerView.Adapter<MyAdapter.ViewHolder>() {
....
}
val adapter = MyAdapter(items) { item ->
doSomethingWith(item)
}
//如果有多个lambdas, 那么最好是用参数名称区分一下
createDialog(title, description,
onPositiveClick = { yay() },
onNegativeClick = { nay() }
)
someView.setOnClickListener { view -> // if unnamed, it is called `it`
// ...
}
//没有使用的参数 可以使用_
someView.waitForMeasure { _, _, _ ->
// unused parameters can be named as `_`
}
如果需要return, 则使用return@[caller], for example return@onClick.
方法引用
fun acceptsLambda(lambda: () -> Unit) {
if(...) {
lambda() // same as `lambda.invoke()`
}
}
fun doSomething() {
}
fun execute() {
acceptsLambda(::doSomething)
}
typealias
typealias ItemClickListener = (Item) -> Unit
class MyAdapter(
private var items: List<Item>,
private val clickListener: ItemClickListener
): RecyclerView.Adapter<MyAdapter.ViewHolder>() {
....
}
lambdas with receivers
inline fun Realm.runTransaction(crossinline transaction: Realm.() -> Unit) {
val realm = this
realm.executeTransaction {
transaction(realm)
}
}
realm.runTransaction {
insertOrUpdate(Dog("Hello"))
insertOrUpdate(Cat("World"))
}
拓展函数,拓展属性
fun View.show() {
this.visibility = View.VISIBLE
}
fun View.hide() {
this.visibility = View.GONE
}
// myView.visibility = View.VISIBLE
myView.show()
var View.isVisible: Boolean
get() = this.visibility == View.VISIBLE
set(value) {
if (value) {
show()
} else {
hide()
}
}
inline fun Array<Account>.forEachNonDemo(action: (Account) -> Unit) {
this.filter { !it.isDemo() }.forEach(action)
}
fun View.objectAnimate() = ViewPropertyObjectAnimator.animate(this)
fun View.animateFadeOut(duration: Long = 325, hideOnFinish: Boolean = true): Animator = run {
alpha = 1f
objectAnimate()
.alpha(0f)
.setDuration(duration)
.get()
.apply {
if (hideOnFinish) {
onFinish {
hide()
}
}
}
}
fun View.animateFadeIn(duration: Long = 325, showOnStart: Boolean = true): Animator = run {
alpha = 0f
objectAnimate()
.alpha(1f)
.setDuration(duration)
.get()
.apply {
if (showOnStart) {
onStart {
show()
}
}
}
}
标准库里的函数— apply, let, alse, run, with
fun okHttpClient() = OkHttpClient.Builder().apply {
setInterceptor(NetworkInterceptor())
baseUrl(BuildConfig.BASE_URL)
}.build()
fragment.arguments = Bundle().also { bundle ->
bundle.putString("hello", "hello")
}
let和run: let可以让我们执行一个代码块,然后返回一个新的类型,而run执行一个代码块之后,返回this
val domainObject = dao.findFirst<MyClass>().let { DomainObject(it) }
fun someFunction() {
val someValue = "beep" // some local variable you cannot avoid, or scoping functions would make hard to read
return result
}
//等同于
fun someFunction() = run {
val someValue = "beep"
result
}
with 减少冗余代码使用次数
with(recyclerView) {
adapter = MyAdapter()
layoutManager = LinearLayoutManager(this@MyActivity)
}
takeIf,takeUnless
Integer someNumber = bundle.getInt("someNumber", -1);
if(someNumber == -1) {
someNumber = null;
}
val someNumber = bundle.getInt("someNumber", -1).takeIf { it >= 0 }
val someText = bundle.getInt("someNumber", -1).takeIf { it >= 0 }?.let { "$it" }
val someText = bundle.getInt("someNumber", -1).takeIf { it >= 0 }?.let { "$it" } ?: ""
val someText = something.takeIf { condition } ?: throw IllegalArgumentException("$something is invalid")
inline functions(crossinline, noinline)
集合
inline fun <reified T>
val query = realm.where(MyObject::class.java)
val query = realm.where<MyObject>()
sealed classes
sealed class Message {
data class TextMessage(val text: String): Message()
data class PictureMessage(val image: ByteArray): Message()
}
val message = ...
when(message) {
is TextMessage -> println("${message.text}")
is PictureMessage -> sendToFriends(message.image)
}