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

  1. 云栖社区>
  2. 终端研发部>
  3. 博客>
  4. 正文

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

技术小能手 2018-11-14 15:13:43 浏览969
展开阅读全文

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

一、代码优化

1、空指针安全

示例1:

5e8bedea5c565ec69cf4b6da18826b6db32aa596

示例2:

a310da2498f5017244ceb318c2c102736f9ba08e

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

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

2、去除findViewById

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

示例1:

8fecdde4a36a4b2b31172b86555415dc2af3194c

3、使用lamda表达式

示例1:

34f190d0ac582c8aa9a4114393a60bd1fd56cfcf

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

a833da7748f79689fe8464c175ddef7695bf0bef

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

二、新的优秀编程方式:

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

所谓的高阶函数就是

 ●  可以接受函数作为参数
 ●  也可以返回函数作为结果

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

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

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

f6769ce24c1af71bfacae92c1e321e2a0acb9616

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

 ●  一是没有了接口定义
 ●  二是没有了匿名内部类

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

2、协程(Kotlin coroutines)

它能干什么?

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

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

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

以网络请求为例:

81905c46bcf136c44e779a652f21e41ae68eaed6

3、方法扩展

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

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

示例:

0bfacf9077619598d7070ecb6525211e72550eab

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

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

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

4、Kotlin DSL

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

示例:

123e3f0b071055ad4a8d2f240bb21aeed39c588e

这样做的好处:

 ●  比起 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、学习成本低:快速上手指引

2ec741a51aca943794548afdfa0641cc07bff8c7

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

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

示例:

fb965ee096e593697994748b55d1992eba4fb682

转换后

46cf642b53e2d6d55302541eaff163585f6ed9eb

优化写法:

bdc7770bf925e072338a319a32295129c825d1a8

四、Kotlin与java兼容性

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

 ●  Kotlin可以自由的引用Java的代码,反之亦然。
 ●  Kotlin可以现有的全部的Java框架和库
 ●  Java文件可以很轻松的借助插件转成kotlin

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

646cf3a87f3160cd4060b75333f5f161cd1735b0

五、关于性能

在大部分场景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方法

44a8b1422214e5fea4b34c7e93e7937d974a5377

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

d54623176ae53036503b928b0fe13430112aefec

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

543fd3508e5922b2ed9e33095874c113bb488a5a

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

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


原文发布时间为:2018-11-14
本文来自云栖社区合作伙伴“终端研发部”,了解相关信息可以关注“终端研发部”。

网友评论

登录后评论
0/500
评论
技术小能手
+ 关注
所属云栖号: 终端研发部