PRF:20161221 Living Android without Kotlin.md

@DockerChen
This commit is contained in:
wxy 2017-05-08 09:48:30 +08:00
parent d80654fac0
commit 3a48a39f00

View File

@ -1,44 +1,43 @@
没有Kotlin(Android)生活 在没有 Kotlin 的世界与 Android 共舞
============================================================ ============================================================
![](https://cdn-images-1.medium.com/max/2000/1*Fd349rzh3XWwSbCP2IV7zA.jpeg) ![](https://cdn-images-1.medium.com/max/2000/1*Fd349rzh3XWwSbCP2IV7zA.jpeg)
> 开始投入一件事比远离它更容易。Donald Rumsfeld > 开始投入一件事比远离它更容易。Donald Rumsfeld
没有Kotlin的生活就像在触摸板上玩魔兽争霸3。购买鼠标很简单但如果你的新雇主不想让你在生产中使用Kotlin你该怎么办 没有 Kotlin 的生活就像在触摸板上玩魔兽争霸 3。购买鼠标很简单但如果你的新雇主不想让你在生产中使用 Kotlin你该怎么办
下面有一些选择。 下面有一些选择。
* 与你的产品负责人争取获得使用Kotlin的权利。 * 与你的产品负责人争取获得使用 Kotlin 的权利。
* 使用Kotlin并且不告诉其他人因为你知道最好的东西是只适合你的。 * 使用 Kotlin 并且不告诉其他人因为你知道最好的东西是只适合你的。
* 擦掉你的眼泪自豪地使用Java。 * 擦掉你的眼泪,自豪地使用 Java。
想象一下,你在和产品负责人的斗争中失败,作为一个专业的工程师,在没有任何人的允许下你将不会去依靠和使用时髦的技术。我知道这听起来非常恐怖特别当你已经品尝到Kotlin的好处但是又没有失去你的希望 想象一下,你在和产品负责人的斗争中失败,作为一个专业的工程师,你不能在没有同意的情况下私自去使用那些时髦的技术。我知道这听起来非常恐怖,特别当你已经品尝到 Kotlin 的好处时,不过不要失去生活的信念
在文章接下来的部分我想简短地描述一些Kotlin的特征使你通过一些知名的工具和库可以应用到你的Android里的Java代码中去。对于Kotlin和Java一个基本的认识是需要的。 在文章接下来的部分,我想简短地描述一些 Kotlin 的特征,使你通过一些知名的工具和库,可以应用到你的 Android 里的 Java 代码中去。对于 Kotlin 和 Java 的基本认识是需要的。
### 数据类 ### 数据类
你真的已经喜欢上Kotlin的数据类不是吗对于你来说得到`equals()`, `hashCode()`, `toString()``copy()`这些类是很容易的。具体来说,`data`关键字还会按照声明顺序生成对应于属性的`componentN()`函数。 它们用于构造声明。 我想你肯定已经喜欢上 Kotlin 的数据类。对于你来说,得到 `equals()``hashCode()``toString()``copy()` 这些是很容易的。具体来说,`data` 关键字还可以按照声明顺序生成对应于属性的 `componentN()` 函数。 它们用于解构声明。
``` ```
data class Person(val name: String) data class Person(val name: String)
val (riddle) = Person("Peter") val (riddle) = Person("Peter")
println(riddle) println(riddle)
``` ```
你知道什么会被打印吗?确信它不会是从`Person` 类的`toString()` 返回的值。这是构造声明的作用,它赋值从`name`到`riddle`。使用园括号`(riddle)`编译器知道它必须使用构造声明机制。 你知道什么会被打印出来吗?确实,它不会是从 `Person` 类的 `toString()` 返回的值。这是解构声明的作用,它赋值从 `name``riddle`。使用园括号 `(riddle)` 编译器知道它必须使用解构声明机制。
``` ```
val (riddle): String = Person("Peter").component1() val (riddle): String = Person("Peter").component1()
println(riddle) // prints Peter println(riddle) // prints Peter)
view raw
``` ```
>这个代码没编译。它就是展示了构造声明怎么工作的。 > 这个代码没编译。它就是展示了构造声明怎么工作的。
正如你可以看到`data`关键字是一个超级有用的语言特性所以你能做什么把它带到你的Java世界 使用注释处理器并修改抽象语法树。 如果你想更深入请阅读文章末尾列出的文章Project Lombok—Trick Explained 正如你可以看到 `data` 关键字是一个超级有用的语言特性,所以你能做什么把它带到你的 Java 世界? 使用注释处理器并修改抽象语法树Abstract Syntax Tree。 如果你想更深入请阅读文章末尾列出的文章Project Lombok—Trick Explained
使用项目Lombok你可以实现几乎相同的功能`data`关键字提供。 不幸的是,没有办法进行构造声明。 使用项目 Lombok 你可以实现 `data`关键字所提供的几乎相同的功能。 不幸的是,没有办法进行解构声明。
``` ```
import lombok.Data; import lombok.Data;
@ -48,24 +47,23 @@ import lombok.Data;
} }
``` ```
`@Data` 注解生成 `equals()`、`hashCode()` 和 `toString()`。 此外,它为所有字段创建 getter为所有非最终字段创建setter并为所有必填字段final创建构造函数。 值得注意的是Lombok 仅用于编译,因此库代码不会添加到您的最终的 .apk。
`@ Data`注解生成`equals``hashCode`和`toString`。 此外它为所有字段创建getters为所有非最终字段创建setters并为所有必填字段finalals创建构造函数。 值得注意的是Lombok仅用于编译因此库代码不会添加到您的最终的.apk。 ### Lambda 表达式
### Lambda表达式 Android 工程师有一个非常艰难的生活,因为 Android 中缺乏 Java 8 的特性,而且其中之一是 lambda 表达式。 Lambda 是很棒的,因为它们为你减少了成吨的样板。 你可以在回调和流中使用它们。 在 Kotlin 中lambda 表达式是内置的,它们看起来比它们在 Java 中看起来好多了。 此外lambda 的字节码可以直接插入到调用方法的字节码中,因此方法计数不会增加。 它可以使用内联函数。
Android工程师有一个非常艰难的生活因为Android中缺乏Java 8的特性而且其中之一是lambda表达式。 Lambdas是很棒的因为它们为你减少了成吨的样板。 你可以在回调和流中使用它们。 在Kotlin中lambda表达式是内置的它们看起来比它们在Java中看起来好多了。 此外lambda的字节码可以直接插入到调用方法的字节码中因此方法计数不会增加。 它可以使用内联函数。
``` ```
button.setOnClickListener { println("Hello World") } button.setOnClickListener { println("Hello World") }
``` ```
最近Google宣布在Android中支持Java 8的特性由于Jack编译器你可以在你的代码中使用lambdas。还要提及的是它们在API 23或者更低的级别都可用。
最近 Google 宣布在 Android 中支持 Java 8 的特性,由于 Jack 编译器,你可以在你的代码中使用 lambda。还要提及的是它们在 API 23 或者更低的级别都可用。
``` ```
button.setOnClickListener(view -> System.out.println("Hello World!")); button.setOnClickListener(view -> System.out.println("Hello World!"));
``` ```
怎样使用它们?就只用添加下面几行到你的` build.gradle `文件中。 怎样使用它们?就只用添加下面几行到你的 `build.gradle` 文件中。
``` ```
defaultConfig { defaultConfig {
@ -80,7 +78,8 @@ compileOptions {
} }
``` ```
如果你不是一个Jack编译器的粉丝或则你由于一些原因不能使用它这里有一个不同的解决方案提供给你。Retrolambda项目允许你使用Java 76或者5上的lambda表达式来运行Java 8的代码下面是设置过程。 如果你不喜欢用 Jack 编译器或者你由于一些原因不能使用它这里有一个不同的解决方案提供给你。Retrolambda 项目允许你在 Java 76 或者 5 上运行带有 lambda 表达式的 Java 8 代码,下面是设置过程。
``` ```
dependencies { dependencies {
classpath 'me.tatarka:gradle-retrolambda:3.4.0' classpath 'me.tatarka:gradle-retrolambda:3.4.0'
@ -93,16 +92,16 @@ compileOptions {
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
``` ```
正如我前面提到的在Kotlin下的lambdas内联函数不增加方法计数但是如何在Jack或者Retrolambda下使用它们 显然,它们不是免费的,隐藏的成本如下。
正如我前面提到的,在 Kotlin 下的 lambda 内联函数不增加方法计数,但是如何在 Jack 或者 Retrolambda 下使用它们呢? 显然,它们不是没成本的,隐藏的成本如下。
![](https://cdn-images-1.medium.com/max/800/1*H7h2MB2auMslMkdaDtqAfg.png)
![](https://cdn-images-1.medium.com/max/800/1*H7h2MB2auMslMkdaDtqAfg.png) *该表展示了使用不同版本的 Retrolambda 和 Jack 编译器生成的方法数量。该比较结果来自 Jake Wharton 的“[探索 Java 的隐藏成本](http://jakewharton.com/exploring-java-hidden-costs/)” 技术讨论之中。*
### 数据操作 ### 数据操作
Kotlin 引入了高阶函数作为流的替代。 当您必须将一组数据转换为另一组数据或过滤集合时,它们非常有用。
Kotlin引入了高阶函数作为流的替代。 当您必须将一组数据转换为另一组数据或过滤集合时,它们非常有用。
``` ```
fun foo(persons: MutableList<Person>) { fun foo(persons: MutableList<Person>) {
@ -116,8 +115,7 @@ fun foo(persons: MutableList<Person>) {
data class Person(val name: String, val age: Int) data class Person(val name: String, val age: Int)
``` ```
Streams也由Google使用Jack编译器提供。 不幸的是Jack不使用Lombok因为它在编译代码时跳过生成中间的`.class`文件而Lombok依赖于这些文件。 流也由 Google 通过 Jack 编译器提供。 不幸的是Jack 不使用 Lombok因为它在编译代码时跳过生成中间的 `.class` 文件,而 Lombok 却依赖于这些文件。
``` ```
void foo(List<Person> persons) { void foo(List<Person> persons) {
@ -143,9 +141,9 @@ class Person {
} }
``` ```
太好了以至于不是真的,所以在哪里捉住? 悲伤的是流从API 24 \可用。谷歌做的不错,但为什么广泛的应用程序有` minSdkVersion = 24 ` 简直太好了,所以 catch 在哪里? 令人悲伤的是,流从 API 24 才可用。谷歌做了好事,但哪个应用程序有用 `minSdkVersion = 24`
幸运的是Android平台有一个很好的开源社区提供许多很棒的库。Lightweight-Stream-API是其中的一个它包含基于Java 7及以下版本的迭代器的流实现。 幸运的是Android 平台有一个很好的提供许多很棒的库的开源社区。Lightweight-Stream-API 就是其中的一个,它包含了 Java 7 及以下版本的基于迭代器的流实现。
``` ```
import lombok.Data; import lombok.Data;
@ -166,14 +164,13 @@ void foo(List<Person> persons) {
} }
``` ```
上面的例子结合了LombokRetrolambda和Lightweight-Stream-API它看起来几乎和Kotlin一样好不是。 使用静态工厂方法允许您将任何Iterable转换为流并对其应用lambdas就像Java 8流一样。 将静态调用` Stream.of(persons) `包装为Iterable类型的扩展函数是完美的但是Java不支持它。 上面的例子结合了 Lombok、Retrolambda 和 Lightweight-Stream-API它看起来几乎和 Kotlin 一样棒。使用静态工厂方法允许您将任何 Iterable 转换为流,并对其应用 lambda就像 Java 8 流一样。 将静态调用 `Stream.of(persons)` 包装为 Iterable 类型的扩展函数是完美的,但是 Java 不支持它。
### 扩展功能 ### 扩展函数
扩展机制提供了向类添加功能而无需继承它的能力。 这个众所周知的概念非常适合Android世界这就是Kotlin在社区很受欢迎的原因。 扩展机制提供了向类添加功能而无需继承它的能力。 这个众所周知的概念非常适合 Android 世界,这就是 Kotlin 在该社区很受欢迎的原因。
有没有技术或魔术将扩展功能添加到你的Java工具箱 由于Lombok你可以使用它们作为一个实验功能。 根据Lombok文档的说明他们想把它从实验状态移出没有或微小的变化很快。 让我们重构最后一个样例,并将` Stream.of(persons) `包装成扩展函数。
有没有技术或魔术将扩展功能添加到你的 Java 工具箱? 因 Lombok你可以使用它们作为一个实验功能。 根据 Lombok 文档的说明,他们想把它从实验状态移出,基本上没有什么变化的话很快。 让我们重构最后一个例子,并将 `Stream.of(persons)` 包装成扩展函数。
``` ```
import lombok.Data; import lombok.Data;
@ -203,17 +200,14 @@ class Streams {
} }
``` ```
所有的方法是`public``static`,并且至少有一个参数的类型不是原始的,被认为是扩展方法。 `@ ExtensionMethod`注解允许你指定一个包含你的扩展函数的类。 而不是使用一个`.class`对象,你也可以传递数组 所有的方法是 `public`、`static` 的,并且至少有一个参数的类型不是原始的,因而是扩展方法。 `@ExtensionMethod` 注解允许你指定一个包含你的扩展函数的类。 你也可以传递数组,而不是使用一个 `.class` 对象。
* * * * * *
我完全知道我的一些想法是非常有争议的特别是Lombok我也知道有很多的库可以使你的生活更轻松。请不要犹豫在评论里分享你的经验。干杯! 我完全知道我的一些想法是非常有争议的,特别是 Lombok我也知道有很多的库可以使你的生活更轻松。请不要犹豫在评论里分享你的经验。干杯!
![](https://cdn-images-1.medium.com/max/800/1*peB9mmElOn6xwR3eH0HXXA.png) ![](https://cdn-images-1.medium.com/max/800/1*peB9mmElOn6xwR3eH0HXXA.png)
--------------------------------- ---------------------------------
作者简介: 作者简介:
@ -224,11 +218,11 @@ Coder and professional dreamer @ Grid Dynamics
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
via: https://hackernoon.com/living-android-without-kotlin-db7391a2b170#.q95i5232f via: https://medium.com/proandroiddev/living-android-without-kotlin-db7391a2b170
作者:[Piotr Ślesarew][a] 作者:[Piotr Ślesarew][a]
译者:[DockerChen](https://github.com/DockerChen) 译者:[DockerChen](https://github.com/DockerChen)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出