前言
这次继续来搞kt,接着kt开发的100个Tips,之前的系列: juejin.cn/post/724929... Kotlin开发的100个Tips (一)
juejin.cn/post/731160... Kotlin开发的100个Tips (二)
21. for循环的until另一种写法 (1.9.0新特性)
平时我们写for循环会有两种写法
scss
for (i in 0.. 5) // 输出 012345
和
scss
for (i in 0 until 5) // 输出 01234
但是我觉得until这个关键字看上去不太舒服,我现在可以这样写
scss
for (i in 0 ..< 5) // 也是输出 01234
在这个场景下,..<的效果和until的效果一样,但看着会更舒服些
22. 数组的forEach获取数组中的位置
平时我们在java中对List做循环
ini
List<String> list = new ArrayList();
for (int i = 0; i < list.size(); i++) {
String a = list.get(i);
}
但是用kt来写的话一般直接用forEach来做
ini
val list = ArrayList<String>()
list.forEach {
val a = it
}
但是如果我们想在循环中获取index,很多新手不懂怎么写,只能通过像java一样写个for循环,其实list有个方法forEachIndexed
ini
val list = ArrayList<String>()
list.forEachIndexed { index, s ->
val a = s
val i = index
}
这样就能获取到index了
23. 创建线程
因为kotlin的lambda表达式的特性,创建线程的写法也会非常的简洁
bash
Log.d("mmp","----线程A ${Thread.currentThread().name}")
Thread{
Log.d("mmp","----线程B ${Thread.currentThread().name}")
}.start()
24. kotlin的关键字注解
比如我们给变量用Volatile修饰,在kotlin中可以这样写
kotlin
@Volatile
private var a: Int? = null
使用一个注解的方法去实现,点开它,发现是一个JvmFlagAnnotation.kt文件,里面还定义了其他注解
less
@Target(FIELD)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
public actual annotation class Volatile
@Target(FIELD)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
public actual annotation class Transient
@Target(FUNCTION, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER, CLASS)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
public actual annotation class Strictfp
@Target(FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
public actual annotation class Synchronized
@Target(EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@SinceKotlin("1.8")
public actual annotation class JvmSerializableLambda
Volatile和Synchronized都是用于线程安全,Strictfp用于精确浮点,Transient和JvmSerializableLambda都是用于序列化,其中JvmSerializableLambda是用来序列化lambda表达式。
Volatile、Synchronized、Strictfp和Transient都是java中的关键字,可以看出kt使用注解的方式去实现这个效果。
25. 获取数组的第一个元素
这个是业务上基本都会有的一个小操作,比如说本来后台应该返回一个对象的,但是因为一些原因他和你说他会返回一个数组,你拿数组中第一个元素就行。或者后台返回一个有序数组,我们只需要拿数组中的最大/最小元素,就是拿第一个就行。如果你细心观察,你会发现业务上会有这样的场景存在。
如果用Java来做这个功能,我们可能需要写
scss
if(list != null && list.size() > 0)
但是kt能快速的实现这个效果
ini
val first = list?.firstOrNull()
这样的写法看起来又舒服,代码也整洁,也安全,不管list是空,还是list数组为空,还是list的第一个元素是空,都会返回空。
26. takeIf 带逻辑的判断
这个关键字的使用场景比较微妙,如果不熟的话,很多场景可以用你也会想不到要用他,所以这个是一个偏经验的关键字。简单来说,就是用在一些复杂的判断场景。
(可以写一段伪代码)假如我有个变量存在本地,这个对象包含了日期、次数、用户id,我要判断日期是今天并且次数小于3,才拿这个用户id去做一些操作
kotlin
val userId = SpUtils().get("key")?.takeId{
return DateUtlis.isToday(it.date) && (it.count < 3)
}?.id
如果条件达成,就能正常拿到id,如果不达成条件,userId就会为空。除此之外还有takeUnless可以辅助takeIf来使用,这里就不多介绍了。
27. 数组做补全操作
可能会有一些需求,比如我要显示9张卡片,由服务端返回卡片列表,如果不满九张的话,没有的卡片就显示+号,那么就需要做一些数组补全的操作。
kt中可以快速实现这个效果
ini
val list = getServiceList()
val paddedList = list + List(9 - list.size) { null }
这样在recyclerview的Item中判断数据为空就显示+号
28. data类的get方法
平时我们写data都是这样写
kotlin
data class User(var name : String?)
但是假设我想调用user.name获取参数的时候做一些操作,返回不同的结果,我就需要在getName()中做操作,那对于data类要怎么去写它的某个属性的get方法呢,其实可以这样写
kotlin
data class User(var id : String?){
@SerializedName("name")
var name: String? = null
get() {
return NicknameCache.getNickName(id) ?: field
}
}
29. 使用标签辅助跳出多层循环
kotlin中可以使用标签来跳出多层判断或者多层循环,当然不用标签也是能实现的,只不过会显得代码比较复杂,而且使用标签的话,一眼就能看出跳出哪一层,并且代码也相对简洁
例如可以这样写
kotlin
loop@ for (i in 1..3) {
for (j in 1..3) {
if (i == 2 && j == 2) {
break@loop // 使用标签来跳出外部循环
}
}
}
这里的loop@就是标签,break@loop就会跳到外层的for循环。
30. 交换变量
这个是一个小技巧,一般的的业务功能是很少出现这种场景,但是涉及算法和优化的场景,是会涉及到两个变量交互。
正常来说,我们按照Java的思路会这样写
ini
var temp = a
a = b
b = temp
用一个中间变量来辅助交换,但是在kt中可以这样做
css
a = b.apply { b = a }