Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android SDK

适用于Android的Java 8:使用Lambda表达式的简介代码

by
Read Time:15 minsLanguages:
This post is part of a series called Java 8 for Android Development.
Java 8 for Android Development: Default and Static Methods

Chinese (Simplified) (中文(简体)) translation by Zhang Xiang Liang (you can also view the original English article)

Lambda表达式可以帮助您从项目中移除样板代码并轻松处理大量数据。看看如何深入了解您今天可以在Android项目中开始使用的Java 8功能。 

Java 8 for Android

2014年3月首次推出的Java 8向编程语言迈进了一大步,它引入了一系列功能,这些功能可以使Java编码变得比以前更简单,更简洁。

不幸的是,Android开发人员暂时不会感受到这些功能的好处,因为谷歌在弃用Jack之前试图通过Jack(Java Android Compiler Kit)将Java 8引入Android平台,以支持在Android Studio中原生支持Java 8。

现在,随着Android Studio 3.0的发布,我们终于有了一个Android工具链版本,它内置了对Java 8最重要的一些功能的支持。

在本系列中,我将向您展示如何从项目中删除大量样板代码,轻松处理大量数据,甚至在Java 8编程中拥有更实用的风格。我们将深入了解您现在可以开始使用的Java 8功能。

在完成本系列时,您将准备好在Android项目中使用以下所有Java 8功能:

  • lambda表达式
  • 方法引用
  • 默认方法
  • 静态接口方法
  • 键入注释
  • 重复注释
  • 功能接口
  • Stream API

在第一篇文章中,我们将看看Java 8第一次发布时产生最多嗡嗡声的特性,并且这有助于为Android开发人员带来最大的不同:lambda表达式。

准备你的开发环境

在开始使用任何 Java 8功能之前,您需要确保您的开发环境已设置为支持此版本的Java。

如果您尚未安装Java 8,那么您需要下载最新的JDK8并更新Android Studio的JDK路径,以便它指向JDK8软件包:

  • 启动Android Studio。
  • 从Android Studio工具栏中选择File> Project Structure ...
  • 更新JDK位置字段,以便它指向新下载的JDK8软件包。

如果您不确定您安装的是哪个版本的Java,那么可以通过打开终端窗口(如果您是Mac用户)或命令提示符(如果您在Windows上)来检查,然后运行以下命令命令:

如果它返回1.8或更高版本,那么你很好走!

您还需要安装Android Studio 3.0 Preview 1或更高版本,但为了减少遇到错误和其他奇怪行为的机会,建议您安装最新版本的Android Studio 3.0--无论是测试版还是预览版,或者,理想情况下,是一个稳定版本的Android Studio 3.0(在撰写本文时尚未提供)。 

接下来,您需要对项目build.gradle文件进行一些更改。通常,您只需添加几行代码即可指定该项目应生成Java 8字节码。但是,如果您以前使用Jack编译器或流行的Retrolambda项目对Java 8功能进行了试验,那么在项目可以使用Android默认工具链提供的新增和改进的Java 8支持之前,您需要禁用这些工具。

在下面的章节中,我将向您展示如何启用Java 8支持,以及如何在需要时禁用Retrolambda和Jack。

将Java 8支持添加到新项目

假设您之前没有启用Jack或将Retrolambda添加为项目依赖项,则第一步是打开您的项目级build.gradle文件并确保您使用的是适用于Android的Gradle版本3.0.0-alpha1(或更高版本)插入:

接下来,打开build.gradle您要使用Java 8功能的每个模块级文件,并将源代码的语言级别和生成的Java字节码的版本设置为JavaVersion.VERSION_1_8

如果你从Jack迁移

Jack编译器可能会被弃用,但只要启用它,您的项目将使用由Jack提供的Java 8支持,而不是Android默认工具链提供的支持。

使用不推荐使用的工具永远不是一个好主意,但是如果你还没有从Jack编译器迁移出来,还有一些额外的原因。

首先,Jack可能会支持Java 8功能的一个子集,但与默认工具链不同,它不支持使用这些功能的第三方库,所以通过使用Jack,您立即就第三方库限制了您的选择。

其次,Jack编译器需要Java代码并将其直接转换为dex,而不产生任何中间字节码。只要启用了Jack,您将无法使用任何依赖此中间输出的工具,例如注释处理器和字节码分析器。

要禁用Jack编译器,请打开您的模块级build.gradle文件并删除该jackOptions部分,但请确保compileOptions完整地保留该块:

如果你从Retrolambda迁移

与Jack类似,Retrolambda不支持使用Java 8语言功能的第三方库。如果您的项目设置为使用Retrolambda插件,那么您应该删除此插件,以便您的项目可以恢复为默认工具链。

打开您的项目级build.gradle文件并将Retrolambda作为项目依赖项移除:

然后,从每个模块级build.gradle文件中删除Retrolambda插件:

测试您的Java 8支持

验证您的项目现在可以支持Java 8的最简单方法是编写快速的lambda表达式,并查看您的项目是否仍在编译。

将一个按钮添加到您的用户界面(或使用已存在的按钮),然后onClickListener 使用lambda表达式为此按钮实现一个按钮。不要担心,如果下面的代码现在没有多大意义 - 这将在本文结尾!

Test your lambda expression by triggering the Java 8 toastTest your lambda expression by triggering the Java 8 toastTest your lambda expression by triggering the Java 8 toast

检查您的项目是否仍然编译,通过从出现的横幅中选择同步,或从Android Studio工具栏中选择工具> Android>使用Gradle文件同步项目

如果Android Studio不会引发任何错误,那么您就可以开始使用本文开头列出的所有功能,包括lambda表达式!

为什么Lambda表达式如此重要?

Lambda表达式很容易成为Java 8最大的新功能,并且可以对创建几乎任何Android应用程序时需要编写的样板代码数量产生巨大影响。

本质上,lambda表达式表示一个不属于任何类的函数,并且可以轻松传递,然后按需执行。

此功能消除了许多Android开发人员在Java方面经历的长期挫折:作为一种面向对象的语言,传递代码块总是感觉比应该更困难。例如,如果您想创建一个新线程,然后将一些代码传递给该线程,那么您通常必须通过匿名实现Runnable接口来实例化一个线程 - 这只是为了传递一些代码而做的很多工作!通过提供一种将函数传递给方法的简单方法,lambda表达式有可能简化您作为Android开发人员执行的一些最常见任务。 通过提供一种将函数传递给方法的简单方法,lambda表达式有可能简化您作为Android开发人员执行的一些最常见任务。

对于任何希望采用功能更强大的编程方法的Java开发人员来说,Lambda表达式也将是一个受欢迎的补充。在Java 8之前,以功能风格进行编码将不可避免地要求您编写大量样板代码,但现在您可以使用lambda表达式传递函数,以较少面向对象的方式编写Java代码,而不必涉及写了大量的匿名类。

如何创建Lambda表达式?

您可以使用以下语法创建一个lambda表达式:

箭头运算符是不言而喻的,但是您应该如何构造lambda的参数和表达式的规则可以根据您要实现的内容而有所不同,因此我们来更详细地探讨这两个元素。

参数

参数是一个或多个参数,它们几乎总是用圆括号括起来。即使你的lambda表达式没有任何参数,你仍然需要提供空的括号,例如:

这个规则的例外是当你的方法有一个推断出它的类型的单个参数时,在这种情况下你可以省略括号:

您可以在参数中使用多个参数,方法是用逗号分隔每个参数:

类型推断在lambdas中是可能的,所以你通常可以从你的参数中省略数据类型。但是,如果编译器无法推断数据类型,则需要在参数前添加类型:

表达体

表达式主体是您要执行的代码,可以是单个表达式或多行代码。如果你想要执行多行代码,那么你需要用大括号括住代码的这一部分来创建一个语句块:

如果你的表达式返回一个值,那么它必须返回一个return语句,例如:

在您的Android应用中使用Lambda表达式

现在我们对可以构造lambda表达式的各种方式进行了概述,让我们来看看一些最常见的场景,您可以在Android开发工作中使用lambda表达式。

Lambdas进行事件处理

典型的Android应用程序必须能够响应各种各样的用户输入事件,并且lambda表达式可以使此事件处理更直接。

在下面的代码中,我们使用一个匿名类来创建一个onClickListener带有重写onClick方法的实例。很有可能,你已经无数次地写了这样的代码。

通过用lambda表达式重写上述代码,我们可以删除以下所有内容:

  • 类实例化: new View.OnClickListener()
  • 访问修饰符,方法名称和类型: public void onClick(View view)
  • 和参数类型,所以你不必写 View view

这意味着我们可以使用单行来实现完全相同的功能:

Lambdas用于多线程

多线程是lambda表达式可以帮助您编写更简洁的代码的另一种常见方案。默认情况下,Android具有一个UI(用户界面)线程,负责处理所有用户交互,将事件分派到相应的UI小部件以及修改用户界面。只要您用任何长时间运行或密集型操作阻止此UI线程,您的应用程序就会变得无响应,甚至可能触发Android的ANR(应用程序无响应)对话框。因此,创建其他线程并分配代码以在这些线程上运行通常是Android开发的重要组成部分。 只要您用任何长时间运行或密集型操作阻止此UI线程,您的应用程序就会变得无响应,甚至可能触发Android的ANR(应用程序无响应)对话框。因此,创建其他线程并分配代码以在这些线程上运行通常是Android开发的重要组成部分。

在Java 8之前,分配代码以在其他线程上运行需要您创建一个实现该Runnable接口的匿名类:

或者,您可以使用Runnable接口的匿名实现来实例化新线程:

用lambda表达式替换这个匿名类可以使这个频繁执行的任务很多更简洁:

最后,如果您使用的是RxJava或RxAndroid库,那么您可以使用lambda表达式来帮助您创建observables。

在这里,我们正在创建一个简单的命令Observable,将hello world字符串 发送给它的所有字符串Observers

使用lambda表达式可以让你Action1用一行代替所有的代码:

在您的 实际代码中使用Lambda表达式

在阅读了一个新功能背后的所有理论之后,下一个挑战就是养成使用这个新功能的习惯。对于像lambda这样的设计用来代替熟悉的样板代码的设计来说,这可能会特别困难,因为总会有一种简单回归你所知的诱惑。

Android Studio有一些功能可以帮助您最终推动使用闪亮的新lambda表达式替换熟悉而笨重的代码。

第一个功能是Android Studio的意图操作菜单,它可以将任何兼容的匿名类自动转换为等效的lambda表达式。如果您不确定如何编写lambda格式的特定代码,那么这非常完美:只需像往常一样编写代码,然后使用intent操作菜单的自动转换功能即可。

要将匿名类自动转换为lambda表达式:

  • 将光标悬停在匿名类上,Android Studio应该显示一个工具提示,通知您它可以将这段代码转换为lambda表达式。
  • 按下Mac的Alt / Option-Enter键,或者如果您是Windows或Linux用户,请使用Alt-Enter快捷键。
  • 从上下文菜单中选择Replace with lambda选项。

Select Replace with lambda from the context menu that appearsSelect Replace with lambda from the context menu that appearsSelect Replace with lambda from the context menu that appears

或者,您可以使用Android Studio的检测工具在整个项目中标记每个可以用lambda表达式替换的匿名类。然后,您可以手动重写每个匿名类,也可以让Android Studio的自动转换功能向您演示如何完成。

突出显示Android Studio可能用lambda表达式替换的每个匿名类:

  • 从Android Studio工具栏中选择分析>按名称运行检查
  • 在出现的弹出窗口中,开始输入匿名类型可以替换为lambda,然后在出现在下拉菜单中时选择该选项。

Select Anonymous type can be replaced with lambda from the Enter inspection name popupSelect Anonymous type can be replaced with lambda from the Enter inspection name popupSelect Anonymous type can be replaced with lambda from the Enter inspection name popup

  • 在随后的窗口中,选择整个项目来标记项目中的每个匿名类。或者,您可以指定Android Studio应执行此检查的个别模块或文件。
  • 点击确定
  • 从Android Studio工具栏中选择分析>检查代码

“检查结果”窗格现在应显示并显示可用Lambda表达式替换的所有匿名类的列表。要仔细查看一个匿名类,只需在“ 检查结果”窗口中双击该类,Android Studio将打开该文件并带您到包含此特定匿名类的确切行。

要用lambda表达式替换当前选定的匿名类,请单击“ 替换为lambda”按钮。

In the Inspection Results window select the Replace with lambda button In the Inspection Results window select the Replace with lambda button In the Inspection Results window select the Replace with lambda button

如果Android Studio未自动打开检查结果窗口,则可以通过从Android Studio工具栏中选择视图>工具窗口>检查结果手动启动它。如果检查结果未出现在工具Windows子菜单中,则可能需要先从Android Studio工具栏中选择分析>检查代码...

测试Lambda表达式

尽管lambda表达式提供了许多好处,但在将其添加到代码之前,您应该知道一个主要缺点。由于lambda没有名称,因此不能直接从测试代码中调用它们,因此向项目添加大量lambda表达式可能会使测试更加困难。

理想情况下,您的lambda表达式应该太简单而不会中断,因此无法对它们进行单元测试应该不是太大的问题。然而,如果你确实需要测试lambda,那么你总是可以像处理私有方法一样对待它,并且单元测试结果,而不是lambda本身。或者,您可以将lambda表达式重构为其自己的方法,因此您可以直接引用它,因此可以正常进行测试。   或者,您可以将lambda表达式重构为其自己的方法,因此您可以直接引用它,因此可以正常进行测试。  

结论

在这篇关于Java 8语言特性的第一篇文章中,我们研究了如何设置Android项目以支持Java 8,以及如何通过用lambda表达式替换匿名类来减少样板代码。 

在下一篇文章中,我将向您展示如何通过将lambda表达式与方法引用相结合来修剪Android项目中的更多代码,以及如何使用默认和静态接口方法来增强接口。

同时,查看一些关于Android应用程序开发的其他文章!

关注我们的公众号
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.