当前位置:   article > 正文

es java 更新api_支持更新的Java语言API

corelibrarydesugaring configuration contains no dependencies

es java 更新api

Imagine developing an app where you need to deal with time calculations. After some googling, you’ll most likely end up finding great samples with the java.time package! However, after releasing your app, suddenly you get thousands of crashes and complaints from users on API < 26!

想象一下开发一个需要处理时间计算的应用程序。 经过一番探索之后,您很可能最终会使用java.time包找到出色的示例! 但是,发布您的应用程序后,突然之间您会收到成千上万的崩溃和API <26上的用户抱怨!

Want to know the reason? Watch the video or read the blog below.

想知道原因吗? 观看视频或阅读下面的博客。

The reason is that the devices which encountered the issues simply didn’t ship with the necessary classes, as at the time those classes were not part of Android.

原因是遇到问题的设备根本没有附带必需的类,因为当时这些类还不是Android的一部分。

With each new release of Android additional java.* APIs are added from OpenJDK to Android. In Android 11, we added support for a number of APIs from newer OpenJDK releases all the way up to version 13, including additions to List, Set, Map, and the new java.time API. While we continuously add new Java APIs to each platform release, we also want to make these APIs available for older devices.

随Android的每个新发行版一起,从OpenJDK向Android添加了其他java。* API。 在Android 11中,我们从最新的OpenJDK版本一直到版本13添加了对许多API的支持,包括对List,Set,Map和新的java.time API的添加。 在我们不断向每个平台版本中添加新的Java API的同时,我们也希望使这些API可用于较旧的设备。

What if I told you that when you use Android Gradle Plugin 4.0.0 and newer, you can now use several hundred APIs from newer OpenJDK versions and your app will work on any Android device? Some of these newer Java APIs in Android 11 are supported through backporting while other APIs are also available via desugaring on older devices where the Android platform does not have the APIs on the runtime.

如果我告诉您,当您使用Android Gradle Plugin 4.0.0及更高版本时,现在可以使用数百个来自OpenJDK较新版本的API,并且您的应用程序可以在任何Android设备上运行吗? 通过向后移植支持Android 11中的其中一些较新的Java API,而在Android平台在运行时没有API的旧设备上,也可以通过删除旧版本提供其他API。

If you are wondering how that is even possible, let’s talk about desugaring.

如果您想知道这怎么可能,让我们谈谈减糖。

D8 / R8脱糖 (D8/R8 Desugaring)

The Android Gradle plugin 4.0 provides built-in support for using certain Java language APIs and third-party libraries that use them. Previously, these APIs were only supported on newer Android versions, but with AGP 4.0 they are now supported on nearly all Android versions.

Android Gradle插件4.0为使用某些Java语言API和使用它们的第三方库提供了内置支持。 以前,这些API仅在较新的Android版本上受支持,但在AGP 4.0中,现在几乎所有Android版本都支持它们。

This support is possible with a trick called desugaring, which is performed by D8/R8. When you build an app using these new Java APIs, the Java compiler first converts Java source code into Java bytecode. Then the toolchain implements the new APIs by performing bytecode transformations on your app including any 3rd-party libraries your app uses, and converts them into dex code while adding the necessary Java 8 runtime code as a separate dex library for devices that are missing those runtime classes.

这种支持可以通过D8 / R8执行的称为减糖的技巧来实现。 使用这些新的Java API构建应用程序时,Java编译器首先将Java源代码转换为Java字节码。 然后,该工具链通过在您的应用程序上执行字节码转换(包括您的应用程序使用的任何第三方库)来实现新的API,并将它们转换为dex代码,同时将必需的Java 8运行时代码作为单独的dex库添加到缺少这些运行时的设备中类。

Image for post

This process is called desugaring and it enables a set of Java 8 APIs to work on all existing devices, except parallel, which is supported from API level 21.

此过程称为desugaring,它使一组Java 8 API可以在除API级别21所支持的并行之外的所有现有设备上工作。

使用较新的Java API (Using newer Java APIs)

To start using the newer Java APIs, update the Android Gradle plugin to 4.0 or higher and add the following configuration in your module’s build.gradle file.

要开始使用较新的Java API,请将Android Gradle插件更新为4.0或更高版本,并在模块的build.gradle文件中添加以下配置。

  • Set coreLibraryDesugaringEnabled flag.

    设置coreLibraryDesugaringEnabled标志。

  • Set Java source and target compatibility to Java 8.

    将Java源和目标兼容性设置为Java 8。
  • Add coreLibraryDesugaring as a dependency.

    添加coreLibraryDesugaring作为依赖项。

  • Enable multidex. To support these language APIs, the plugin compiles a separate DEX file that contains an implementation of the missing APIs and includes it in your app

    启用multidex 。 为了支持这些语言API,该插件会编译一个单独的DEX文件,其中包含缺少的API的实现,并将其包含在您的应用中

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0 -->
  3. android {
  4. defaultConfig {
  5. //Only required when setting minSdkVersion to 20 or lower
  6. multiDexEnabled true
  7. }
  8. compileOptions {
  9. // Flag to enable support for the new language APIs
  10. coreLibraryDesugaringEnabled true
  11. // Sets Java compatibility to Java 8
  12. sourceCompatibility JavaVersion.VERSION_1_8
  13. targetCompatibility JavaVersion.VERSION_1_8
  14. }
  15. }
  16. dependencies {
  17. // Dependency with the implementation code for the APIs
  18. coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5'
  19. }

Now that you’ve learned about and enabled Java 8+ desugaring, let’s take a look at the new APIs.

既然您已经了解并启用了Java 8+除错功能,那么让我们看一下新的API。

java.time (java.time)

The old java.util Time API had some drawbacks. java.util.Date and java.util.Calendar classes are mutable, which can cause concurrency issues. Also, the API is not very consistent and easy to use. To give a simple example, in a Date object, day starts from 1 and month starts from 0, which can be confusing.

old java.util Time API有一些缺点。 java.util.Datejava.util.Calendar类是可变的,这可能会导致并发问题。 而且,该API也不十分一致且易于使用。 举个简单的例子,在Date对象中,day从1开始,month从0开始,这可能会造成混淆。

Date date = new Date(2, 3, 1); //Tue Apr 01 00:00:00 PST 1902

Date date = new Date(2, 3, 1); //Tue Apr 01 00:00:00 PST 1902

With OpenJDK version 8, a new Java Time API, java.time package, is added to Java. The new java.time is based on the popular library JodaTime. All core java.time classes are immutable and don’t have setter methods, so they don’t introduce any concurrency issues. Plus the new java.time API makes working with timezones much easier. Let’s take a look at the new date and time classes.

使用OpenJDK版本8,新的Java Time API(java.time包)已添加到Java。 新的java.time基于流行的库JodaTime 。 所有核心java.time类都是不可变的,并且没有setter方法,因此它们不会引入任何并发问题。 加上新的java.time API,使时区的使用变得更加容易。 让我们看一下新的日期和时间类。

First, if you do not need timezone data on Date and Time objects, java.time has two new classes, LocalDate and LocalTime. These two classes represent date and time relative to the user, such as an alarm clock or a timer, without worrying about timezones.

首先,如果您不需要Date和Time对象上的时区数据,则java.time有两个新类LocalDateLocalTime 。 这两个类别代表相对于用户的日期和时间,例如闹钟或计时器,而无需担心时区。

  1. // Current date
  2. LocalDate date = LocalDate.now();
  3. // Current time
  4. LocalTime time = LocalTime.now();
  5. // Date of Android 11 beta launch
  6. LocalDate date2 = LocalDate.of(2020, 6, 10); //yyyy,MM,dd

If your use case requires timezones, you can use ZonedDateTime or OffsetDateTime classes. Let’s start with ZonedDateTime. ZonedDateTime is an immutable representation of DateTime that holds a LocalDateTime, a ZoneId, and the resolved ZoneOffset.

如果您的用例需要时区,则可以使用ZonedDateTimeOffsetDateTime类。 让我们从ZonedDateTime开始。 ZonedDateTimeDateTime的不可变表示形式,其中包含LocalDateTimeZoneId和已解析的ZoneOffset

Time zones can be set either in abbreviated or long text form of the zone using the ZoneId class.

可以使用ZoneId类以时区的缩写或长文本形式设置时区。

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0
  3. ZonedDateTime currentDate = ZonedDateTime.now();
  4. System.out.println("the current zone is "+ currentDate.getZone());
  5. //the current zone is America/Los_Angeles
  6. ZoneId anotherZone = ZoneId.of(“Europe/Istanbul”);
  7. ZonedDateTime currentDateInIstanbul = currentZone.withZoneSameInstant(anotherZone);
  8. //2020-06-08T23:50:00.159+03:00[Europe/Istanbul]

ZonedDateTime is particularly useful when you need to store date and time without relying on the context of a specific device or app. ZonedDateTime can be resolved to any timezone at any point in time.

当您需要存储日期和时间而不依赖于特定设备或应用程序的上下文时, ZonedDateTime特别有用。 ZonedDateTime可以在任何时间点解析为任何时区。

You can use ZoneOffsets to calculate the difference between the current timezone and Greenwich/UTC.

您可以使用ZoneOffsets计算当前时区与格林威治/ UTC之间的时差。

OffsetDateTime is similar to ZonedDateTime but keeps the offset from Greenwich/UTC instead of ZoneId.

OffsetDateTime类似于ZonedDateTime但继续从格林尼治/ UTC而不是抵消ZoneId

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0 -->
  3. ZoneOffset zoneOffSet= ZoneOffset.of("+03:00");
  4. OffsetDateTime offsetDateTime = OffsetDateTime.now(zoneOffSet);
  5. System.out.println(offsetDateTime);
  6. //2020-06-08T23:50:17.315+03:00

To summarize the differences between ZonedDateTime and OffsetDateTime, ZonedDateTime is great for displaying timezone-sensitive datetime data. OffsetDateTime is best for storing datetime data to a database and other use cases where the data needs to be serialized.

总结一下ZonedDateTimeOffsetDateTime之间的区别, ZonedDateTime非常适合显示时区敏感的日期时间数据。 OffsetDateTime最适合将日期时间数据存储到数据库以及需要序列化数据的其他用例。

The new java.time API has two new classes, Period and Duration, to define a date range or length of time, respectively.

新的java.time API具有两个新类, PeriodDuration ,分别定义日期范围或时间长度。

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0
  3. LocalDate now = LocalDate.now();
  4. LocalDate androidBeta = LocalDate.of(2020, 6, 10);
  5. Period period = Period.between(androidBeta, now);

java.util.stream (java.util.stream)

Streams allow you to perform functional-style operations on collections. Streams do not store data or modify the underlying data structure and offer much better readability.

流使您可以对集合执行功能样式的操作。 流不存储数据也不修改基础数据结构,并且提供了更好的可读性。

Streams have a large number of built-in intermediate and terminal operations. Intermediate operations are lazy and always return a new stream. Terminal operations are eager and once invoked, they complete the traversal of the data source and the stream can no longer be used. Since intermediate operations are not evaluated until terminal operation is invoked, streams may perform better when working on large data sources.

流具有大量内置的中间和终端操作。 中间操作是惰性的,总是返回新的流。 终端操作非常热切,一旦被调用,它们就可以完成数据源的遍历,并且不再可以使用该流。 由于在调用终端操作之前不会评估中间操作,因此在处理大型数据源时,流的性能可能会更好。

To use streams, you can call the stream() method on a collection or use Stream.of() and pass your data source or use the Stream.Builder().

要使用流,可以在集合上调用stream()方法或使用Stream.of()并传递数据源或使用Stream.Builder()

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0 -->
  3. List<person> list = Arrays.asList(personArray);
  4. Stream<Person> stream1 = list.stream();
  5. //or
  6. Stream<Person> stream2 = Stream.of(personArray);
  7. //or
  8. Stream.Builder<Person> streamBuilder = Stream.builder();
  9. for (Person p: personArray){
  10. streamBuilder.accept(p);
  11. }
  12. Stream<Person> stream3 = streamBuilder.build();

其他java.util API (other java.util APIs)

There are new additions to the Map, Collection and Comparator interfaces under java.util package.

java.util包下的Map,Collection和Comparator接口有新增的功能。

Writing a comparator is not hard but requires lots of boilerplate code where you can easily make mistakes. In Java 8, you can use a simple chaining style code to write comparators. With the help of method handles and lambdas, a comparator in Java 8 looks as simple as this.

编写比较器并不难,但是需要大量样板代码,您可以在其中轻松出错。 在Java 8中,可以使用简单的链接样式代码编写比较器。 借助方法句柄和lambda,Java 8中的比较器看起来就这么简单。

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0 -->
  3. import static java.util.Comparator.comparing;
  4. comparing(Person::getFirstname).thenComparing(Person::getSurname);

Another interesting addition to the java.util package is the Optional class and its primitive counterparts OptionalInt, OptionalLong and OptionalDouble. Optional helps you work with real types instead of null references. Optional can represent null with “the absence of the value”. You can use the utility methods to handle values as ‘available’ or ‘not available’ instead of checking null values.

java.util包的另一个有趣的补充是Optional类及其原始对等物OptionalIntOptionalLongOptionalDouble 。 可选帮助您使用实型而不是空引用。 可选可以用“缺少值”表示空值。 您可以使用实用程序方法将值处理为“可用”或“不可用”,而不用检查空值。

  1. <!-- Copyright 2019 Google LLC.
  2. SPDX-License-Identifier: Apache-2.0 -->
  3. Optional<String> opt = Optional.of("Java 8");
  4. if (opt.isPresent()){ //true
  5. //...
  6. }
  7. opt = Optional.ofNullable(null);
  8. if (opt.isEmpty()){ //true
  9. //
  10. }
  11. opt.ifPresent(str -> System.out.println(str)); //false, doesn’t print

The Optional class has a variety of utility methods such as orElse(), orElseThrow(), filter() and more which help you handle null checks and handle null cases easily.

Optional类具有各种实用程序方法,例如orElse()orElseThrow()filter() ,它们可以帮助您轻松处理空检查和处理空情况。

java.util.concurrent (java.util.concurrent)

Java 8+ also introduces new methods on AtomicInteger, AtomicLong and AtomicReference in the java.util.concurrent.atomic package. Another update in java.util.concurrent package is bug fixes to the ConcurrentHashMap, a thread-safe alternative to HashMap. ConcurrentHashMap has always been part of Android. However, on API levels 21 and 22, the implementation had a bug. A new fixed implementation is part of the desugared library, and with library desugaring that implementation will be used in your app in place of the one in the platform which might have a bug.

Java 8+还通过java.util.concurrent.atomic包中的AtomicIntegerAtomicLongAtomicReference引入了新方法。 java.util.concurrent包中的另一个更新是对ConcurrentHashMap错误修复, ConcurrentHashMapHashMap的线程安全替代品。 ConcurrentHashMap一直是Android的一部分。 但是,在API级别21和22上,该实现存在一个bug 。 一个新的固定实现是已废弃的库的一部分,并且通过将库重新存储后,该实现将在您的应用中使用,而不是平台中可能存在错误的那个实现。

If you are not familiar with ConcurrentHashMap, this class allows any number of threads to perform get operations, but for update and insert operations, the performing thread must lock the particular segment where the data is modified or inserted. Although any thread can perform get operations, this lock may block get operations that try to access the data in the locked segment. Due to synchronization, ConcurrentHashMap can perform slower than a HashMap.

如果您不熟悉ConcurrentHashMap ,则此类允许任意数量的线程执行get操作,但对于更新和插入操作,执行线程必须锁定修改或插入数据的特定段。 尽管任何线程都可以执行get操作,但此锁可能会阻止尝试访问锁定段中数据的get操作。 由于同步, ConcurrentHashMap执行速度可能比HashMap慢。

Image for post

Please note in Android Studio 4.0 using these library desugared types in instrumented tests is not supported.

请注意,在Android Studio 4.0中,不支持在已测试的测试中使用这些库的已还原类型。

Upgrade your projects to make full use of all newer Java language APIs. Streams, Optionals and the new time APIs help you write less code and introduce fewer errors while using modern language APIs. Make sure to take a look at the full list of supported Java 8+ APIs.

升级项目,以充分利用所有较新的Java语言API。 流,可选和新的时间API可以帮助您在使用现代语言API的同时减少编写代码并减少错误。 确保查看受支持的Java 8+ API的完整列表

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

此页面上的内容和代码示例受 内容许可 中所述的许可的约束 Java是Oracle和/或其附属公司的注册商标。

翻译自: https://medium.com/androiddevelopers/support-for-newer-java-language-apis-bca79fc8ef65

es java 更新api

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/99460
推荐阅读
相关标签
  

闽ICP备14008679号