四个库,让你在 Android 中启用 Java 8 功能

ElizabetRid 7年前
   <p>Java 8 的推出引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时简化了各种设计模式的实现方式,是 Java 有史以来最重要的更新。</p>    <p>自 Android N 之后,由于 Jack&Jill 编译工具链的存在,Java 8 的一些语言功能终于得到了支持。虽然还存在一些限制,如,新编译器附带的数据绑定支持库无法使用,以及注释支持受限等,但这完全不足以否定 Java 8 中存在的其他先进功能。在这篇文章中,作者介绍了在 Android 中引入 Java 8 功能的四个库,希望它们对你有帮助。</p>    <p>文章如果有翻译不到位的地方,欢迎大家进行指正。喜欢的也不要忘了点赞、打赏、收藏哦~</p>    <h3>Java 8 在 Android M(6.0)及更低版本中的功能</h3>    <p>Java 8 的发布引入了一些新特性。在所有功能中较为重要的有 lambda 表达式,方法引用,Stream API 和新的时间日期 API。</p>    <p>目前,Jack&Jill 编译工具链还处于早期开发阶段,它比较容易与 Java 7 保持同步。另外,很幸运的是,现在有几款库还能将 Android 中 的 Java 8 移植到更低版本的编译器中。让我们来看看它们是如何发挥作用的。</p>    <h3>Lambda 表达式</h3>    <p>伴随 Java 8 的发布而发布的 lambda 表达式,允许你使用参数传递代码块。它们可以用于代替类的匿名实例,例如,对单击按钮时执行的操作进行定义。下面我演示了使用匿名类和 lambda 表达式在按钮上设置 onClick 监听器:</p>    <pre>  <code class="language-java">// Anonymous class approach:  button.setOnClickListener(new View.OnClickListener() {      @Override      public void onClick(View view) {          // onClick action here      }  });</code></pre>    <pre>  <code class="language-java">// Lambda expresssion approach:  button.setOnClickListener(view -> {      // onClick action here  });</code></pre>    <p>用 Retrolambda 实现 Java 6 和 7 中的 Lambda 表达式功能</p>    <p>使用 Retrolambda 能很快实现 Java 6 和 Java 7中的Lambda 表达式功能,将它应用在 Android 上也是一样。Retrolambda 能转换 Java 8 编译的字节码,以便它在更低版本的 Java 中运行此代码,而不需要任何附加的依赖关系。</p>    <p>要在 Android Studio 项目中使用 retrolambda,需要将下列代码添加到项目级别的 build.gradle 文件中:</p>    <pre>  <code class="language-java">buildscript {      repositories {          jcenter()          mavenCentral()      }      dependencies {          classpath 'com.android.tools.build:gradle:2.1.2'          classpath 'me.tatarka:gradle-retrolambda:3.2.5'      }  }  ...</code></pre>    <p>模块级 build.gradle 文件应包含以下突出显示的代码行:</p>    <pre>  <code class="language-java">apply plugin: 'com.android.application'  apply plugin: 'me.tatarka.retrolambda'    android {      compileSdkVersion 23      buildToolsVersion "24.0.1"        defaultConfig {          applicationId "com.example.lambdas"          minSdkVersion 16          targetSdkVersion 23          versionCode 1          versionName "1.0"      }        buildTypes {          release {              minifyEnabled false              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'          }      }        compileOptions {          sourceCompatibility JavaVersion.VERSION_1_8          targetCompatibility JavaVersion.VERSION_1_8      }  }</code></pre>    <p>遵循以上步骤,你已经能够成功地在 Android上启用 Java 8 的其中一项功能。</p>    <h3>方法引用(Method References)</h3>    <p>方法引用可以很方便地与 lambda 表达式一起使用,以简化语法。例如,如果一个 lambda 表达式主体包含一个类方法调用,它可以替换为一个方法引用:</p>    <pre>  <code class="language-java">Arrays.sort(new Integer[] {1, 2, 3},      (first, second) -> first.compareTo(second));</code></pre>    <pre>  <code class="language-java">Arrays.sort(new Integer[] {1, 2, 3}, Integer::compareTo);</code></pre>    <p>参数会自动提供以匹配方法签名(method signature)。</p>    <p>这里存在三种::运算符用法:</p>    <ul>     <li>object::instanceMethod</li>     <li>Class::staticMethod </li>     <li>Class::instanceMethod</li>    </ul>    <p>你可点击 此处 了解更多有关方法引用和构造函数引用的信息。</p>    <p>如果你已经使用 retrolambda 库启用了 lambda 表达式,方法引用此时也能正常运行,因为此功能是包含在内的。如果没有,请你参考上一节的内容。</p>    <h3>Stream API</h3>    <p>Java 8 另一个了不起的语言特性就是 Stream API,Stream 表示抽象层,允许开发人员以声明方式处理底层数据。它的另一个好处就是能对 Stream 采取并行执行操作,这有利于开发人员有效地处理大量数据,而不必为并发和线程管理担心。</p>    <p>例如,我们有一个数字列表,需要过滤出小于 10 的数字,然后返回其余的排序列表。使用 Stream API,事代码表现更美观:</p>    <pre>  <code class="language-java">List<Integer> numbers = new ArrayList<>();  numbers.addAll(Arrays.asList(1, 20, 3, 10, 20, 30, 4, 50, 80, 1, 2));    List<String> large_number = numbers.stream()          .filter(num -> num >= 10)          .sorted()          .collect(Collectors.toList());</code></pre>    <p>这仅是 Stream API 提供的一个简单示例。 有关 Java 中的 Stream 的更多信息,请参阅 <a href="/misc/goto?guid=4959728635786560597" rel="nofollow,noindex">Java 8 中的 Stream API</a> 。</p>    <p>在 Android 中,我们有两个库,可以从 Stream API 中选择,我们来看下:</p>    <p>Lightweight-Stream-API</p>    <p>Lightweight-Stream-API 库将 Stream API 反向运行到 Java 7,并通过使用迭代器重写 API 来降低版本。该库在原始 Java 8 实现中提供了许多 Stream 操作符,其中有一些是新的,如:sortBy,groupBy,chunkBy,sample,slidingWindow 等。</p>    <p>将库包含到 Android 项目中是为了给 build.gradle 文件中的依赖项添加单独的一行:</p>    <pre>  <code class="language-java">dependencies {    ...    compile 'com.annimon:stream:1.1.3'    ...  }</code></pre>    <p>由于该库已经重新实现 Stream API 的方式,一些语法会与原始的 Stream 实现不同,并且并行执行也被省略。 </p>    <p>streamsupport</p>    <p>第二个将 Stream API 从 Java 8 回退到更低版本的库就是 streamsupport 库。与 Lighweight-Stream-API 相比,streamsupport 除了具有并行执行功能和 Java 9 的增强功能外,还有一些其他的功能,如,Java 8 的功能接口或可选模式。</p>    <p>为了在您的项目中使用 streamsupport 库,请将以下依赖项添加到 build.gradle 文件中:</p>    <pre>  <code class="language-java">dependencies {      compile 'net.sourceforge.streamsupport:streamsupport:1.5.2'      compile 'net.sourceforge.streamsupport:streamsupport-cfuture:1.5.2'      compile 'net.sourceforge.streamsupport:streamsupport-atomic:1.5.2'      compile 'net.sourceforge.streamsupport:streamsupport-flow:1.5.2'      compile 'net.sourceforge.streamsupport:streamsupport-literal:1.5.2'  }</code></pre>    <h3>新时间日期 API</h3>    <p>Java 8 之前的版本不太支持日期和时间的设置。虽然也有几个支持的 API,但它们各自都存在问题。为解决这些问题,Java 8 带来了新时间日期,你可以点击此处了解更多相关信息。</p>    <p>ThreeTen Android Backport</p>    <p>虽然 Android 不支持 Java 8 中的时间日期 API,但一个名为 ThreeTen Android Backport 的库可以提供相同的功能。</p>    <p>使用之前,请将以下行添加到 build.gradle 文件中:</p>    <pre>  <code class="language-java">compile 'com.jakewharton.threetenabp:threetenabp:1.0.4'</code></pre>    <h3>结论</h3>    <p>在这篇文章中,我介绍了在 Android 中引入 Java 8 功能的四个库。 使用这些库,您可以在 Android 中使用 lambda 表达式,方法引用,Stream API 或新日期时间 API,而无需迁移到新的 Jack&Jill 编译器工具链,同时还能保持与以前版本的 Android 和 Java 的兼容性。</p>    <p> </p>    <p> </p>    <p>来自:https://my.oschina.net/u/2903254/blog/801769</p>    <p> </p>