Kotlin在Android开发中那些让人舒适的地方

/   今日科技快讯   /

近日,抖音发布《2019抖音数据报告》。报告披露了抖音最新的成绩单:截至2020年1月5日,抖音日活跃用户数已经突破4亿。

/   作者简介   /

Hello大家早上好,又是一个悠然的周三,不知不觉一周已悄然过半,今天我们来聊一聊Kotlin。如今我使用Kotlin已有超过两年的时间,用它写过几个开源项目,做过一场直播,还写了本即将出版的书,自我认为应该算得上是半个Kotlin“专家”了。如果你对Kotlin有任何方面的疑问,可以在下方留言,我会尽量帮大家答疑解惑。

本篇文章来自Kn1ght的投稿,分享了他切换到Kotlin开发过程中的心得体会,相信对大家有所帮助。同时也感谢作者贡献的精彩文章!

Kn1ght的博客地址:

https://juejin.im/user/5a4371a9f265da4318770795

/   前言   /

目前公司的项目已经全面使用Kotlin,转换的过程的确不是怎么让人舒适,但是让人欣慰的是结局是让人满意的。Kotlin的确可以让代码简洁,安全并且高效。这里分享一下,在使用Kotlin中那些让人觉得舒适的地方。

  • 字符模板

  • 空安全

  • 延迟加载

  • 方便易读的循环

  • 强大易用的迭代器

  • 默认参数

  • DataClass

  • 简短而强大的标准函数库

  • 通吃的when(结合密封类会让代码更舒适)

  • 扩展

  • 简单的Bundle 快速的Parcelable

/   字符模板   /

开发中难免需要根据多个字段去拼接一条字符串做展示,在过长或者过于复杂的数据逻辑的时候,用Java实现起来都过于冗长。Kotlin 使用 $ 放在变量名的前面去表达字符串中的变量和表达式,从而简化了这一过程。

    val str = "hello"
    // str length : 5
    print("$str length: {$str.length}")

/   空安全   /

在使用Java开发Android的过程中,避免不了大量的空安全判定代码,介于Kotlin要很好的兼容Java,在这个问题上Kotlin设计一整套新的类型系统(这里不作研究)来完善优化它。

所有的类型都分为可空和不可空类型,并且针对不可空类型强制要求初始化,在一开始就让开发者高标准的、严谨的使用变量,是一种规范性的要求。但是可空类型可能会在程序中更广泛的应用,针对这一点,Kotlin也有Elvis 操作符来进行安全访问或者避免空值情况,见简洁代码。

    // 不可空类型(使用前必须初始化)
    var notCanNullInt: Int = 0
    // 可空类型
    var canNullInt: Int? = null
    // 安全访问
    print("${canNullInt?.toShort()}")
    // 避免空值 为空给与一个默认值
    val age = canNullInt ?: 18
    // 为空返回
    val time = canNullInt ?: return

/   延迟加载   /

这一点可以说是对不可空类型的更进一步优化,开发中总有一些变量是在某些时机才会被初始化,而不是类加载的时候就加载。延迟加载是很好的东西,可以省去初始化的成本,在变量真正被需要的时候才被初始化。

    val userInfo: UserInfo by lazy { UserInfo() }
    lateinit var person: InvationPerson

/   方便易读的循环   /

Kotlin有区间的概念,这个概念让创建循环更加易读方便。

    // print :0 1 2 3 4 5 6 7 8 9 10
    for (i in 0..10) {
        print("$i ")
    }
    // print :10 9 8 7 6 5 4 3 2 1 0
    for (i in 10 downTo 0) {
        print("$i ")
    }
    // print :0 2 4 6 8 10
    for (i in 0..10 step 2) {
        print("$i ")
    }
    // print :0 1 2 3 4 5 6 7 8 9
    for (i in 0 until 10) {
        print("$i ")
    }
    val map = mapOf("a" to 1, "b" to 2)
    // print :a - 1 b - 2
    for ((key, value) in map) {
        print("$key - $value")
    }

/   强大易用的迭代器   /

遍历集合是基操,对于一些稍微复杂一点的数据逻辑,Java实现起来并不友好。当然后面有了RxJava来进行补救,不过Kotlin做的似乎要更好一点。(这里就不讨论Kotlin的集合框架架构了)

    val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

    list.forEach { print(it) }
    // 映射
    val listUp = list.map { it + 2 }
    // 过滤
    val listFilter = list.filter { it % 2 == 0 }
    // asSequence 懒处理 map filter中都存在遍历操作 asSequence可以将它们合并起来 只存在一次遍历 提升性能
    val listMore = list.asSequence().map { it + 2 }.filter { it % 2 == 0 }.toList()

asSequence 对提升效率大有裨益,其他的操作就不一一列举了。

/   默认参数   /

重载是很比较常见的操作,但是有时候这种方式会出现很多相同的模板代码。Kotlin的默认参数,可以给参数指定默认值,并且在调用的时候像给变量赋值一样给参数赋值而不用像Java一样非要按照顺序去传值。并且因为具有默认值的原因,所以调用的时候可以根据具体情况传递参数,更加灵活、更加易读和简洁。

    class Point(val x: Float = 0F, val y: Float = 0F)

    val x = Point(x = 10F)// x 10 y 0
    val y = Point(y = 10F)// x 0 y 10
    val xy = Point(x = 10F, y = 10F)// x10 y10

/   DataClass   /

开发中Bean文件是必不可少的,但是Java的Bean文件大部分都是模版代码,虽然有插件自动生成,但是依然会觉得比较繁琐,Kotlin可以将这些类申明为Data类,这些类会默认实现equals(),hashCode(),toString() 和copy() 方法,从几十行Java代码简洁到几行代码,Kotlin只用声明 一个data class。

    data class Person(
        val name: String,
        val age: Int,
        val sex: Int
    ){
        //....
    }

/   简短强大的标准函数库   /

这是Kotlin提供的函数库,使用后会简化不少的样板代码。稍微不一样的地方是它们的this和it各自指向不一样,以及返回值得不一样,使用得时候根据具体得情况来就可以了。

run
val str = "a"
val res = str.run{
    // this 指向 "a" it没有指向
    // 可以直接访问对象得属性
    print(length)
    1 // 最后一行返回值为1
}

let

val str = "a"
val res = str.let{
    // this 指向当前class
    // it 指向a
    print(it.length)
    "let" // 返回值"let"
}

with

val res = with(user){
    // this 指向user it无指向
    println(age)
    println(name)
    "with" // 返回值
}

apply

val str = "a"
val res = a.apply{
    // this指向a it 无指向
    2 // 返回值
}

/   通吃的when   /

对于Java的switch再熟悉不过,但是它使用起来有比较多的限制,有时候面对复杂的逻辑会显得乏力。Kotlin的when表达式可以匹配几乎任何东西(字面值,枚举,数字,范围,类型,表达式,甚至函数(kotlin函数至上)) 简单感受下:

fun whenTest(number: Number?): String {
    return when (number) {
        null, 0 -> "empty"
        1 -> "tiny"
        in 2..5 -> "small"
        is Long -> "big number"
        else -> "unKnow"
    }
}

当然有时候使用when会有一些比较麻烦的事情,比如对else情况的处理,因为你的程序中明明只有这么几种情况,但是你却不得不写上关于else的情况处理,这样的代码让人觉得不安心,也降低了可读性,这个时候可以结合Koltin的密封类来处理,比如对网络情况的回执,对错误的处理,Android对RecyclerView的适配中多中ViewHolder的处理。

// 密封类的存在让整个过程中可能出现的情况更加严谨
sealed class NetWorkResult
data class Success(val resJson: String) : NetWorkResult()
data class Failure(val error: Error) : NetWorkResult()
// 代码更加易读
fun netWorkTest(result: NetWorkResult) {
    when (result) {
        is Success -> {
            showResult(result.resJson)
        }
        is Failure -> {
            showError(result.error)
        }
    }
}

                   

/   扩展   /

扩展可能是最受欢迎的一个特性,因为它可以让你少写很多工具类,并且让代码看起来更易读,更简洁。比如做一个防止重复点击的操作。

// 扩展点击事件属性(重复点击时长)
var <T : View> T.lastClickTime: Long
    set(value) = setTag(1766613352, value)
    get() = getTag(1766613352) as? Long ?: 0
// 重复点击事件绑定    
inline fun <T : View> T.singleClick(time: Long = 800, crossinline block: (T) -> Unit) {
    setOnClickListener {
        val currentTimeMillis = System.currentTimeMillis()
        if (currentTimeMillis - lastClickTime > time || this is Checkable) {
            lastClickTime = currentTimeMillis
            block(this)
        }
    }
}

/   简单的Bundle快速的Parcelable   /

一开始我并没有注意到这个特性,因为项目是组件化开发,在跳转传值上都采用了ARouter,但是当我发现Kotlin对这个做的改造的时候还是非常开心~

// 创建Bundle 和创建map 一样优雅
val bundle = bundleOf(
    "KEY_ONE" to 1,
    "KEY_TWO" to 2L,
    "KEY_THREE" to true 
)
// 再也不用写繁琐的Parcelable实现
@Parcelize
data class Person(val name:String):Parcelable

/   总结   /

已经使用Kotlin完整开发了两个项目,在开发上Kotlin确实能够带来体验很好的语法糖,让开发更高效,让代码更易读。当然这里的只是自己暂时想到一些地方,如果有更多更好的用法,欢迎告知~

推荐阅读:

聊聊Java的GC机制

SP存储apply()和commit()的区别你知道吗?

Android Studio中竟然还能加入一个程序员鼓励师

欢迎关注我的公众号

学习技术或投稿

长按上图,识别图中二维码即可关注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值