您现在的位置是:首页 > 文章详情

不会用kotlin?这篇看完不懂,我跪搓衣板

日期:2018-11-13点击:455

e11b50a2820ad761b8ebd5983f12b37245474f15

最近用kotlin重写了项目中的部分模块,领略到了这个Google官方推荐语言的魅力。

正文

对比Java语言Kotlin有很多优点,如:空指针安全、支持方法扩展、lamda表达式、高阶函数、函数式编程、kotlin协程(用同步的方式写异步代码)等等。Kotlin可以 100%等价替换Java代码,Android Studio 提供了一键把Java代码转义为Kotlin的能力。Kotlin可以无缝和Java代码互相调用,并且极大的提升开发效率,以改写的24小时节目单逻辑类ProgramListLogic为例,java代码行数为415行,用kotlin改写后减少到了329行,减少20.7%代码量。

一、代码优化

1、空指针安全

示例1:

d7089e0efcb0c7ad8dbbb7f0689bb910f8e7c03c

示例2:

aee47f553b04f5e3c085fb94ee41e87eb6805ca8

一句话搞定,?:操作符表示如果 ?: 左侧的表达式值不是null, 就会返回表达式的的值,否则, 返回右侧表达式的值。

上面只是2个比较简单的例子,从中可以看出kotlin可以极大的提升代码的简介性,让我们远离不断判空判空的繁琐,而且kotlin在编译阶段就会报出可能为空的错误,从开始就解除NullPointer风险。

2、去除findViewById

通过kotlin-android-extensions,可以节省findviewbyid(), 实现与Data-Binding,Dagger框架的效果,不需要添加任何额外代码,也不影响任何运行时体验。

示例1:

0e9c80d89ccfb5a39225ecf336cbd3b7254cbcaa

3、使用lamda表达式

示例1:

e43fc8c0f86c880847ebdcb0b1d55d2094156ac4

示例2:带接收者的lambda:with与apply

44ec9ba039bf08c246c19d46077d9fbeb88adc9b

kotlin中还有许多简化代码优的优化点,类似于自动生成set/get, 字符串拼接,when语法,内置了很多的操作符等等,这些都大大减轻了我们的工作负担。

二、新的优秀编程方式:

1、高阶函数与函数式编程:

所谓的高阶函数就是

  • 可以接受函数作为参数

  • 也可以返回函数作为结果

我们可以利用这个特性写出很多优雅简洁的代码。

kotlin 和 java 有一个重要的不同就是函数式编程。在函数式编程的思想中函数是一等公民,在使用 kotlin 时我们要多利用这种思维来思考问题。

示例(使用高阶函数实现回调):

cee27fe72f2e71b733584a3b4e24b885d3ad8d23

用高阶函数实现的代码和之前的代码有两个不同:

  • 一是没有了接口定义

  • 二是没有了匿名内部类

这样的好处是显而易见的,因为少了匿名内部类的使用,在程序运行过程中是提高了性能的

2、协程(Kotlin coroutines)

它能干什么?

它能替换掉Handler,AsyncTask 甚至是Rxjava来优雅的解决异步问题。

协程是由程序直接实现的,是一种轻量级线程,协程是通过编译技术实现(不需要虚拟机VM/操作系统OS的支持),通过插入相关代码来生效!

与之相反,线程/进程是需要虚拟机VM/操作系统OS的支持,通过调度CPU执行生效!

以网络请求为例:

11886f4807fc6d89888ac7ca295b426ce4e0ee80

3、方法扩展

Kotlin 可以对一个类的属性和方法进行扩展,且不需要继承或使用 Decorator 模式。

扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。

示例:

8fcb857fdfd1020ac69e14cd01bef1185c792205

我们对ProgramListPlugin中对ProgramListLogic进行了方法扩展,返回ProgramListLogic的Tag

扩展完美解决了当一个类某一功能并不通用但是不得不写方法或者继承子类实现的问题。只有某些特殊场景使用时,使用扩展函数,从而灵活多变。

此外还可以进行属性扩展,原理是一样的。

4、Kotlin DSL

使用anko-layout库,可以用到牛逼的dsl(领域特定语言)功能,布局的另一种代码方式,相对比较简洁,xml的简易替代。

示例:

b9f0958e8c4701b7000fa35406332d5d17bff03b

这样做的好处:

  • 比起 xml 的繁琐来,这真是要清爽很多

  • 布局本身也是代码,可以灵活复用

  • 再也不用 findViewById 了

  • 事件监听很方便的嵌到布局当中

  • DSL 方式的布局没有运行时的解析的负担

三、成本

1、安装包成本

kotlin复用了java的大部分方法,Kotlin 的标准库只有 7000 个方法,比 support-v4 还要小。Kotlin 具有非常紧凑的运行时库,可以通过使用 ProGuard 进一步减少,编出来的release版本.apk只有80K大小左右的增量。

2、配置成本低

Android Studio 3.0及其以版本上已经直接集成kotlin,无需再安装插件。只需在工程中配置kotlin依赖包。配置如下:

1)在工程根目录build.gradle里配置:

dependencies {
classpath “org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version
}

2)在module的build.gradle里配置:

apply plugin: ‘kotlin-android’
dependencies {
implementation”org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version

3、学习成本低:快速上手指引

b921eadeee7a5e3a5c3ba0c407878f668976c372

Android studio中提供了快速将java转换为kotlin的功能,可以一键将写好的java类转换为kotlin,有些转换后会有错误,改动后就可以正常的跑起来了,它可以帮助我们快速上手kotlin代码,给出写法示例。

但是通过这个方法转换后的kotlin代码比较生硬,基本是1:1转换的,不会用到比较好的语法糖,转换后我们仍有比较多可以优化的点,这里例举一些:

示例:

259e8a74bd1b6c3afe5d62b1f78a01a2f66c89cf

转换后

8c34344d2479b12775b8a41c6a57f5ebc2055c25

优化写法:

3c32947a5ce6f159618e0d1894b7b9b83cf35e70

四、Kotlin与java兼容性

Kotlin和Java都属于基于JVM的编程语言。Kotlin和Java的交互性很好,可以说是无缝连接。表现在

  • Kotlin可以自由的引用Java的代码,反之亦然。

  • Kotlin可以现有的全部的Java框架和库

  • Java文件可以很轻松的借助插件转成kotlin

下面是一段kotlin调用java代码,可以看到基本调用方法是一致的。

5d3a99ab13d2b068982694a9899678dbc0d5fee5

五、关于性能

在大部分场景Kotlin的执行效率和Java代码的执行效率一致。由于非常相似的字节码结构,Kotlin 应用程序的运行速度与 Java 类似。

随着 Kotlin 对内联函数的支持,在部分场景Kotlin执行效率会更高一些,例如使用 lambda 表达式的代码通常比用 Java 写的代码运行得更快。因为:Kotlin提供了方法的inline设置,可以设置某些高频方法进行inline操作,减少了运行时的进栈出栈和保存状态的开销。

六、编译效率

Java在clean构建比Kotlin稍快,但这些情况很少。 对于大多数开发人员来说,更常见的情况是部分构建,其中增量编译进行了大量改进。 随着Gradle daemon运行和增量编译的开启,Kotlin编译速度与java一样快或略快于Java。

增加kotlin编译速度的一些方法:

  • 开启gradle daemon,即在~/.gradle/gradle.properties文件中,增加org.gradle.daemon=true

  • 在项目的gradle.properties中增加kotlin.incremental=true 开启kotlin的增量编译。

这里有一篇对比kotlin和java编译速度的文章:

https://medium.com/keepsafe-engineering/kotlin-vs-java-compilation-speed-e6c174b39b5d?swoff=true

其中对kotlin和java各种情况下的编译做了全方位的详细对比。

七、遇到的坑

1、编译出现的方法数64K问题

Error:The number of method references in a .dex file cannot exceed 64K.

在工程已经使用multidex对dex进行分片处理的情况下,仍出现了这个错误,实在令人费解。

最后发现是因为工程中引入的com.antfortune.freeline库导致的,Freeline是由阿里团队开发的一款针对Android平台的增量编译工具,它可以充分利用缓存文件,类似于instantrun。怀疑在引进kotlin后,因为这个库导致没有对kotlin编译的dex没作分片导致Kotlin的方法ID超出了[0, 0xffff]的范畴。

这个freeline库在新版本中已弃用,不会再有这个问题。

2、直接Convert Java File to Kotlin File带来的坑

在接口中如果有定义get方法

6bb067614d4e180026c805a2263d42c3fe6339f0

因为Kotlin是对属性自带set,get方法的,在转换为kotlin后会被转换成这样

4b5947a70618918bca5c1156adcf8cc3f21278b9

如果实现接口的类中,之前有个成员变量也是title

2d77fd0297cab70fa84bde5bd59061439aaea67f

则当给title赋值时,会造成循环调用,导致ANR。

Kotlin仍有很多很好用的特性、语法糖、API等着我们探寻。

5a9d94003274a80696258d52b32aa9d5d92cc4e6

Kotlin文档地址:

http://kotlinlang.org/docs/reference

kotlin在线开发地址:

http://kotlinlang.org/docs/reference

原文地址:

http://www.jarrywang.com/?p=31


原文发布时间为:2018-11-14

本文作者:程序员 

本文来自云栖社区合作伙伴“终端研发部”,了解相关信息可以关注“终端研发部”。


原文链接:https://yq.aliyun.com/articles/669017
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章