【翻译】Kotlin 1.1 新版本同样适合安卓开发者

2017-04-29 by Liuqingwen | Tags: Kotlin 翻译 | Hits

一、前言

本文是一篇翻译文,尽量遵照了原文的意思,加上本人英语水平有限,第一次做翻译,如有不当之处请多包涵!

二、正文

标题:Kotlin 1.1 新版本同样适合安卓开发者
2017年4月5号由 Roman Belov 发布
这是一篇邀请文,由 Antonio Leiva 编写,一位安卓工程师、培训导师,也是《Kotlin for Android Developers》书的作者

Kotlin 1.1 的发布真是激动人心啊!新版本的新特性对于 Java 开发者来说非常有用,将给整个 JVM 开发界带来新的可能。

但是这些新特性,比如协程,或者类型别名(举个列子)的特性,看起来似乎和安卓开发者沾不上边。

我们仍然挣扎在低效率的、古老的 Java 6 版本中,以至于大部分开发者都忘记了还有其他平台的存在。

那么有一个很严肃的问题是: Kotlin 团队能否在带来新特性的同时保持对 Java 6 的兼容性呢?这个问题的回答是肯定的!

所有的新特性仍然适用于 Java 6 ,同时作为扩展而适用于安卓开发者。更重要的是,今天我就要把这些都展示给您,让您知道在开发安卓程序过程中是多么的爽快。

  • 类型别名:让你的事件监听更具可读性

当然,类型别名是有很多用处的。但是在我看来首当其冲的是在使用 lambda 表达式的时候能够让事件监听增加可读性。

如果之前你都还没有听说过类型别名的话,那我告诉你其实它的功能就是简单地重命名复杂的类型,使其更加具有可读性。

比如你有个 RecyclerViewadapter 类会接收一个事件监听。众所周知, RecyclerViewListView 一样没有标准的处理单项视图点击事件的方式,所以我们必须动手自己写。

假设我们有个事件监听需要访问这个视图,我们的适配器类就像下面这样:

1
2
3
class MyAdapter(val items: List<Item>, val listener: (View) -> Unit) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
...
}

同时你的 ViewHolder 可能也需要接收这个监听事件,把它赋值给这个视图的点击事件监听者:

1
2
3
4
5
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: Item, listener: (View) -> Unit) {
itemView.setOnClickListener(listener)
}
}

这种情况并不复杂,如你所见,在上下文之外,我们需要多次重复定义这个 lambda 表达式导致代码可读性降低。

但是,我们可以使用类型别名来表示一个点击事件监听者: typealias ClickListener = (View) -> Unit
这样我们就能在任意需要这个事件监听的地方使用它,像这样: class MyAdapter(val items: List<Item>, val listener: ClickListener) 或者 fun bind(item: Item, listener: ClickListener) { ... }

  • 数据类的功能更加强大

数据类非常有用,因为它避免了大量的重复模板工作。但是他们在某些功能上的缺乏使得在有些场所并不能派上用场。

Kotlin 1.1 中引入的一个新特性就是继承性:数据类也可以继承自其他类。这就允许数据类成为封装类的一部分:

1
2
3
4
5
sealed class UiOp {
object Show : UiOp()
object Hide : UiOp()
data class Translate(val axis: Axis, val amount: Int): UiOp()
}

现在,封装类可以在父类之外定义了,就像这样:

1
2
3
4
sealed class UiOp
object Show : UiOp()
object Hide : UiOp()
data class Translate(val axis: Axis, val amount: Int)
  • lambda 表达式的解构体

数据类在最初始的版本中就能够使用解构体,那是多亏了自动生成的 componentX() 方法。你可以把数据类的内容用这样的方式同时赋值给多个变量:

1
2
3
data class Item(val text: String, val url: String)

val (text, url) = item

但是之前,这个非常有用而强大的特性却不能在 lambda 表达式中使用。现在这种方式被改变了,你可以像这样做:

1
2
3
4
fun bind(item: Item) = item.let { (text, url) ->
textView.text = text
imageView.loadUrl(url)
}

这确实对于双元素或者字典中键值对设置非常有用,打个比方。

  • 局部属性代理

属性代理被证明很有用,能够给类中的属性带来额外的效果。

比如,一个很有用处的例子就是懒加载代理,它能延迟赋值的执行直到这个属性第一次被使用。

懒加载对于局部变量也是很有用的,但是 Kotlin 却没有这样的特性。

现在,我们可以这样使用局部属性代理:

1
2
3
4
5
6
7
8
9
10
fun testLocalDelegation() {
val database by lazy { createDatabase() }
val cache by lazy { createMemoryCache() }

if (mustUseDatabase()) {
database.use { ... }
} else {
cache.use { ... }
}
}

尽管这个例子完全可以不使用懒加载来做,但是这有助于我们理解相关概念。

有一些相当耗资源的操作我们可能会执行也可能不会。通过使用懒加载,我们可以延迟资源的实例化直到我们必须使用它。

当第一次运行的时候,大括号里的代码就会被执行,同时也会缓存起来供之后使用。

  • 再也不要管理那些 lambda 表达式中不需要使用的变量了

有一种常见的情形就是:我们在 lambda 表达式中所定义的参数到最后都不能派上用场。

这是因为在 Kotlin 1.0 版本中我们没有一种有效的方式来抛弃那些不需要使用的参数。

举个例子,在文章的前面我解释了如何使用代理更新一个 RecyclerView 的适配器,后面的代码是这样的:

1
2
3
4
var items: List<Content> by Delegates.observable(emptyList()) {
prop, old, new ->
autoNotify(old, new) { o, n -> o.id == n.id }
}

这个 prop 参数并没有用上,但是却必须要有它的定义。现在,你可以采用下划线来避免这种情况:

1
2
3
4
var items: List<Content> by Delegates.observable(emptyList()) {
_, old, new ->
autoNotify(old, new) { o, n -> o.id == n.id }
}

不过还有一种最糟糕的情况就是所有的参数你都不会使用。如果你的 lambda 表达式中有多个参数,尽管你不会使用但是你必须全部写出来。

现在,我们可以这样忽略他们:

1
2
3
4
var items: List<Item> by Delegates.observable(emptyList()) {
_, _, _ ->
notifyDataSetChanged()
}

这不仅使得我们减少了变量的定义,还能让代码更具有可读性。现在,你不需要去判断哪些参数用了哪些没用。这真是一清二楚!

  • 协程

在 Kotlin 1.1 中协程是一个令人振奋的新闻。尽管最后发布的依然是带有“实验性”的包,不过它已经功能齐全并且从今天开始你也可以开始在你的项目中使用了!

协程能够让你像写同步代码块一样写异步代码,能够编写流畅的代码使得在某刻挂起任务的执行以等待结果的返回。

想必你有可能已经知道 Kotlin 中协程并不是一个库或者一种特殊的实现,它是一种语言特性,允许我们通过它创造实用的库。

因此,即使我们同样实现的代码看上去大同小异,但很重要的一点就是我们懂得协程归更到底是创建了子线程并在主线程中返回得到结果,这在安卓中尤为重要。

辛运的是, Kotlin 团队开发极其迅速,已经有好些库把协程的威力带到了安卓开发中。这里有几个例子:

第一个是你很可能希望看到的 Jetbrains 官方提供的库:

  • kotlinx-coroutines-android ,这个库实现了协程在安卓中的使用。
  • Anko ,这个库的最新 beta 版本已经包含了协程对很多框架的支持。

同时也还有很多第三方库实现了他们自己版本的协程:

我强烈建议你们不仅要会使用他们,还要去看看他们是如何实现的。这也是开源的魅力所在!

  • 其他一些对于安卓开发者来说很酷的事情

在这个版本中还有很多其他的改进,但是我想重点提出几个关于针对安卓开发的功能。

第一个就是:你现在可以启用 Jack 编译器了,通过这样的设置: jackOptions { true } 。尽管谷歌已经宣布放弃 Jack 工具链,但是如果你还在 Java 8 中使用它,那么在 Android Studio 2.4 版本的的最终发布前,这会对你很有用。

另外一个,将会有一个新的潮流就是使用 @JvmOverloads 来实现自定义视图组件的构造函数,这从文字意义上来说就是可以用一句话来实现自定义视图的构造函数(不过确实是很长的一句话),通过一个构造函数和默认的参数值:

1
2
3
4
5
class CustomView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
...
}
  • 结论

Kotlin 1.1 带来的一大堆惊艳的特性毫无征兆地质问着我们:为什么还要继续使用 Java 呢?

Kotlin 带给安卓开发者的益处毋庸置疑,你完全可以从今天开始就使用 Kotlin 来开发安卓软件。

另外,如果你想学习使用 Kotlin 来开发安卓程序,那么你会对《[Kotlin for Android Developers]》(https://antonioleiva.com/kotlin-android-developers-book/)这本书感兴趣的。

这边文章发布在类目:安卓访客文章新闻标签下,订阅他的永久地址
原文地址:https://blog.jetbrains.com/kotlin/2017/04/kotlin-1-1-is-also-for-android-developers/

PS: 文中代码格式错乱,已更新,于 2018-10-27


Comments: