当前位置: 首页 > 科技观察

在没有Kotlin的世界中与Android共舞

时间:2023-03-15 08:45:56 科技观察

开始致力于一件事比远离它更容易。—DonaldRumsfeld没有Kotlin的生活就像在触摸板上玩魔兽争霸3。买鼠标很容易,但如果您的新雇主不希望您在生产中使用Kotlin怎么办?这里有一些选项。与您的产品负责人争夺对Kotlin的访问权限。使用Kotlin,不要告诉别人,因为您知道最好的东西只适合您。擦干眼泪,自豪地使用Java。想象一下,你输掉了与产品负责人的战斗,作为一名专业的工程师,你不能擅自使用那些时髦的技术。我知道这听起来很可怕,尤其是当您尝到了Kotlin的好处时,但不要对生活失去信心。在本文的下一部分中,我想简要介绍一下Kotlin的一些特性,您可以通过一些知名的工具和库将这些特性应用到Android中的Java代码中。需要Kotlin和Java的基本知识。数据类我想你一定喜欢Kotlin的数据类。你很容易得到equals()、hashCode()、toString()和copy()。具体来说,data关键字也可以按照声明的顺序生成属性对应的componentN()函数。它们用于解构声明。dataclassPerson(valname:String)val(riddle)=Person("Peter")println(riddle)你知道会打印什么吗?实际上,它不会是Person类的toString()返回的值。这就是解构声明所做的,它将名称分配给谜语。括号(谜语)的使用告诉编译器它必须使用解构声明机制。val(riddle):String=Person("Peter").component1()println(riddle)//printsPeter)此代码未编译。它只是展示了构造声明是如何工作的。如您所见,data关键字是一种非常有用的语言特性,那么您可以做些什么来将它带入您的Java世界呢?使用注释处理器并修改抽象语法树。如果你想更深入,请阅读文末列出的文章(ProjectLombok—TrickExplained)。使用projectLombok,您可以获得与data关键字提供的几乎相同的功能。不幸的是,没有办法进行解构声明。importlombok.Data;@DataclassPerson{finalStringname;}@Data注释生成equals()、hashCode()和toString()。此外,它为所有字段创建getter,为所有非final字段创建setter,并为所有必需(最终)字段创建构造函数。值得注意的是,Lombok仅用于编译,因此库代码不会添加到您最终的.apk中。Lambda表达式由于Android中缺少Java8功能,Android工程师的生活非常艰难,其中之一就是lambda表达式。Lambda很棒,因为它们可以为您节省大量的样板文件。您可以在回调和流中使用它们。在Kotlin中,lambda表达式是内置的,它们看起来比在Java中看起来好多了。此外,lambda的字节码可以直接插入到调用方法的字节码中,因此方法计数不会增加。它可以使用内联函数。button.setOnClickListener{println("HelloWorld")}最近,Google宣布支持Android中的Java8功能,感谢Jack编译器,您可以在代码中使用lambda。还要提一下,它们都可以在API23或更低版本上使用。button.setOnClickListener(view->System.out.println("HelloWorld!"));如何使用它们?只需将以下行添加到您的build.gradle文件中。defaultConfig{jackOptions{enabledtrue}}compileOptions{sourceCompatibilityJavaVersion.VERSION_1_8targetCompatibilityJavaVersion.VERSION_1_8}如果您不喜欢使用Jack编译器,或者由于某种原因不能使用它,这里有一个不同的解决方案。Retrolambda项目允许您在Java7、6或5上运行带有lambda表达式的Java8代码,以下是设置方法。dependencies{classpath'me.tatarka:gradle-retrolambda:3.4.0'}applyplugin:'me.tatarka.retrolambda'compileOptions{sourceCompatibilityJavaVersion.VERSION_1_8targetCompatibilityJavaVersion.VERSION_1_8}正如我前面提到的,Kotlin下的lambdaintrinsics不会增加方法数,但是如何在Jack或Retrolambda下使用它们?显然,它们不是免费的,隐性成本如下。该表显示了使用不同版本的Retrolambda和Jack编译器生成的方法数。这个比较来自JakeWharton的“ExploringJava'sHiddenCosts”技术讨论。数据操作Kotlin引入了高阶函数来替代流。当您必须将一组数据转换为另一组数据或过滤集合时,它们很有用。funfoo(persons:MutableList){persons.filter{it.age>=21}.filter{it.name.startsWith("P")}.map{it.name}.sorted().forEach(::println)}dataclassPerson(valname:String,valage:Int)流也由Google通过Jack编译器提供。不幸的是,Jack没有使用Lombok,因为它编译代码并跳过生成Lombok所依赖的中间.class文件。voidfoo(Listpersons){persons.stream().filter(it->it.getAge()>=21).filter(it->it.getName().startsWith("P")).map(Person::getName).sorted().forEach(System.out::println);}classPerson{finalprivateStringname;finalprivateintage;publicPerson(Stringname,intage){this.name=name;this.age=age;}StringgetName(){returnname;}intgetAge(){returnage;}}这很好,那么问题在哪里呢?遗憾的是,流只能从API24获得。谷歌做得很好,但minSdkVersion=24是哪个应用程序?幸运的是,Android平台有一个很棒的开源社区,提供了很多很棒的库。Lightweight-Stream-API就是其中之一,它包括用于Java7及以下版本的基于迭代器的流实现。importlombok.Data;importcom.annimon.stream.Stream;voidfoo(Listpersons){Stream.of(persons).filter(it->it.getAge()>=21).filter(it->it.getName().startsWith("P")).map(Person::getName).sorted().forEach(System.out::println);}@DataclassPerson{finalStringname;finalintage;}上面的例子结合了Lombok,Retrolambda和Lightweight-Stream-API,它看起来几乎和Kotlin一样好。使用静态工厂方法可以将任何Iterable转换为流并对其应用lambda,就像Java8流一样。将静态调用Stream.of(persons)包装为Iterable类型的扩展函数是完美的,但Java不支持它。扩展功能扩展机制提供了在不继承类的情况下向类添加功能的能力。这个众所周知的概念非常适合Android世界,这就是Kotlin在这个社区中非常受欢迎的原因。有没有什么技巧或魔法可以为您的Java工具箱添加扩展?感谢Lombok,您可以将它们用作实验性功能。根据Lombok文档,他们希望将其从实验状态中移出,基本上如果没有什么变化的话。让我们重构最后一个示例并将Stream.of(persons)包装到扩展函数中。importlombok.Data;importlombok.experimental.ExtensionMethod;@ExtensionMethod(Streams.class)publicclassFoo{voidfoo(Listpersons){persons.toStream().filter(it->it.getAge()>=21).filter(it->it.getName().startsWith("P")).map(Person::getName).sorted().forEach(System.out::println);}}@DataclassPerson{finalStringname;finalintage;}classStreams{staticStreamtoStream(Listlist){returnStream.of(list);}}所有方法都是public和static的,至少有一个参数类型不是原始的,所以是扩展方法。@ExtensionMethod注释允许您指定一个包含您的扩展函数的类。您还可以传递数组而不是使用.class对象。我很清楚我的一些想法很有争议,尤其是Lombok,我也知道有很多库可以让你的生活更轻松。请不要犹豫,在评论中分享您的经验。干杯!