@JvmOverloads
在Kotlin中,在有默认参数值的方法中使用 @JvmOverloads 注解,就可以很方便地实现多个重载方法。最常使用的地方就是自定义 View,代码示例如下:
class MyView @JvmOverloads constructor(context:Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = 0): View(context, attributeSet, defStyleAttr) {
}
它等价于如下 java 代码:
public class MyView extends View {
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
Parcelable 序列化
在 Android 开发中,如果需要使用 Parcelable
来实现序列化,就需要写一堆模板代码。而在 kotlin 中,你可以很简单地通过 @Parcelize
就可以实现相同的效果。
首先,我们需要先引入插件,代码如下:
plugins {
id 'kotlin-parcelize'
}
然后,在需要需要实现 Parcelable
序列化的地方,加上 @Parcelize
注解就可以了。这样就不用写一大堆的模板代码。
import kotlinx.parcelize.Parcelize
@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable
data class
data class User(val name: String, val age: Int, val gender: Int)
在Java中我们常常使用Java bean来保存数据对象,在 Kotlin 中直接提供了数据类来处理这种情况。在 Kotlin 当中,编译器会为数据类自动生成一些有用的方法。它们分别是:equals()
、hashCode()
、toString()
componentN()
和 copy()
等等。
其中 componentN()
方法可以让我们对对象解构, copy()
方法可以让我们只修改其中一个值,代码示例如下:
val user = User("小明", 18, 0)
// 解构
val (name, age, gender) = user
// 只需求其中的姓名
val user1 = user.copy(name = "小军")
在使用 data class
时,有三点需要注意,分别是:
data class
的构造函数至少需要有一个参数。data class
不能被继承,不能加 open 关键字。data class
不是深拷贝,需要自己处理
runCatching
runCatching {
// 执行一段可能异常的代码
}.onSuccess {
// 执行成功
}.onFailure {
// 发生异常
}
使用 runCatching
取代 java 风格的 try-catch,可以很清晰地处理成功或者失败地情况。
runInterruptible
在 kotlin 协程中,我们使用 cancel
来取消任务;而在 Java 多线程中,我们使用 interrupt
方法来中断线程。如果你对这两个方法都不了解,可以看我之前写的java多线程面试系列——旧版api 和 kotlin 协程入门教程 。
现在考虑这样一种情况,如果我们在 kotlin 协程中,用到了 Java 的并发集合,比如说 LinkedBlockingQueue
,ArrayBlockingQueue
等等,这时候我们调用了它的阻塞接口,我们使用 cancel
能中断当前线程,并且 cancel
当前协程吗?
答案是不行的,我们还需要调用 interrupt
方法才可以完全停止这个任务。不过我们不需要太过担心这个问题,kotlin 考虑到了这种情况,提供了 runInterruptible
方法来内部处理这种情况。我们只需要像之前一样调用 cancel
就可以了,它内部会判断线程的状态,并执行 interrupt
方法。代码示例如下:
class Test {
suspend fun test() {
runInterruptible { // 内部会调用 interrupt 方法
while (true){
Thread.sleep(100)
println("do something")
}
}
}
}
fun main(): Unit = runBlocking {
val t = Test()
val job = launch(Dispatchers.IO) {
t.test()
}
delay(500)
job.cancel() // 这里只需要 cancel 就可以了
delay(1000)
println("end")
}
measureTimeMillis
在 Android 开发中,我们常常需要测试 SDK 初始化或者执行一些操作的耗时。在 kotlin 中,我们可以简单地使用 measureTimeMillis
来实现这个功能。代码示例如下:
val spendTime = measureTimeMillis {
// 初始化SDK或者执行一些操作
}
withTimeout 和 withTimeoutOrNull
在 Android 开发中,我们需要确保每一次操作地耗时不要太长,即有一个超时失败地机制。在 kotlin 中,我们可以通过 withTimeout
和 withTimeoutOrNull
方法来简单地实现。其中 withTimeout
在超时时会抛出异常,而 withTimeoutOrNull
只会返回一个 null 值。代码示例如下:
runCatching {
// withTimeout 会抛出异常,需要 runCatching 包裹
val result = withTimeout(5000) {
}
}
val result = withTimeoutOrNull(5000) {
}