注意:此答案在技术上是正确的,但现在已过时
Java 8+ API desugaring支持现在可通过Android Gradle插件4.0.0+使用
(另请参见Basil Bourque下面的答案)
ThreeTenABP库的开发正在逐渐结束。请考虑在未来几个月内切换到Android Gradle插件4.0、java.time.*和其核心库desugaring功能。
要在任何版本的Android平台上启用对这些语言API的支持,请将Android插件更新为4.0.0(或更高版本),并在您的模块的build.gradle文件中包含以下内容(从Android Developers网站上的Java 8支持页面的此部分中获取,该页面还提供有关desugaring的其他信息):
android {
defaultConfig {
multiDexEnabled true
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5'
}
原始答案
第一个发现:为什么你必须使用ThreeTenABP而不是java.time、ThreeTen-Backport或者甚至是Joda-Time
这只是定义新标准的非常漫长过程的简短版本。所有这些包基本上都是相同的东西:它们提供了Java中良好的、现代的时间处理功能。差异微妙但重要。
最明显的解决方案是使用内置的java.time
包,因为这是Java中处理时间和日期的新标准方式。它是JSR 310的实现,这是一个基于Joda-Time库的新标准提案。
然而,java.time
是在Java 8中引入的。Android直到Marshmallow运行在Java 7上("Android N"是第一个引入Java 8语言特性的版本)。因此,除非你只针对Android N Nougat及以上版本,否则不能依赖于Java 8语言特性(我不确定这是否完全正确,但这是我的理解)。所以java.time
不适用。
下一个选择可能是
Joda-Time,因为
JSR 310是基于Joda-Time的。然而,正如
ThreeTenABP readme所指出的那样,由于许多原因,Joda-Time并不是最佳选择。
接下来是
ThreeTen-Backport,它将Java 8的大部分(但不是全部)
java.time
功能向后移植到Java 7。这对于大多数用例来说都很好,但正如
ThreeTenABP readme中所指出的那样,它在Android上存在性能问题。
所以最后一个看起来正确的选项是ThreeTenABP。
第二个发现:构建工具和依赖管理
由于编译程序(尤其是使用大量外部库的程序)非常复杂,Java几乎总是使用"构建工具"来管理该过程。Make、Apache Ant、Apache Maven和Gradle都是用于Java程序的构建工具(请参见this post进行比较)。正如下文所述,Gradle是Android项目选择的构建工具。
这些构建工具包括依赖管理。Apache Maven似乎是第一个引入集中式软件包仓库的工具。Maven引入了
Maven中央仓库,它提供了与php的
composer
和Ruby的
gem
以rubygems.org相当的功能。换句话说,Maven中央仓库对于Maven(和Gradle)来说就像Packagist对于composer一样,是一个版本化软件包的权威和安全来源。
第三个发现:Gradle在Android项目中处理依赖关系
我计划阅读Gradle文档
here,包括他们的免费电子书。如果我几周前在学习Android时已经阅读了这些文档,我肯定会知道Gradle可以使用Maven中央仓库来管理Android项目的依赖关系。此外,正如
this StackOverflow答案中详细说明的那样,在Android Studio 0.8.9版本之后,Gradle通过Bintray的JCenter隐式使用Maven中央仓库,这意味着您不需要进行额外的配置来设置仓库,只需列出所需的依赖即可。
第四个发现:项目依赖在 [项目目录]/app/build.gradle 中列出
对于那些有使用过 Java Gradle 的经验的人来说,这一点是显而易见的,但我花了一些时间才弄明白。如果你看到有人说“哦,只需添加 compile 'this-or-that.jar'
”或类似的话,那么要知道,compile
是 build.gradle 文件中的指示编译时依赖关系的指令。这是官方Gradle页面上有关依赖管理的链接。
第五个发现:ThreeTenABP 由Jake Wharton管理,而不是由 ThreeTen 管理
又是一个让我花费了太多时间去解决的问题。如果你在 Maven Central 中搜索 ThreeTen,你只会看到 threetenbp
的包,而没有 threetenabp
。如果你去 ThreeTenABP的 GitHub 代码库, 你会在 Readme 的下载部分中看到那行臭名昭著的compile 'this-or-that'
代码。
当我第一次进入这个github仓库时,我不知道那个编译行是什么意思,于是我试图在我的终端中运行它(显然会失败)。我感到沮丧,直到我弄清楚了其他的东西,很久之后才回来看,最终意识到它是一个指向
com.jakewharton.threetenabp
仓库的Maven Repo行,而不是
org.threeten
仓库。这就是为什么我认为ThreeTenABP包不在Maven仓库中。
现在一切都变得非常容易。您可以通过确保您的
[project folder]/app/build.gradle
文件在其
dependencies
部分中具有
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
行来在Android项目中获得现代时间处理功能:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "me.ahuman.myapp"
minSdkVersion 11
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:23.4.0'
implementation 'com.android.support:design:23.4.0'
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
}
同时将此代码添加到Application类中:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
AndroidThreeTen.init(this);
}
}
onCreate()
中调用AndroidThreeTen.init(this)
。参见ThreeTen-Backport error on Android - ZoneRulesException: No time-zone data files registered。 - Ole V.V.