218

我问这个问题是因为我是 Java 和 Android 的新手,我搜索了几个小时试图弄清楚这一点。答案来自相关答案的组合,所以我想我会记录我所学到的知识,以供其他可能正在苦苦挣扎的人使用。见答案。

我正在使用 Android Studio 2.1.2,我的 Java 设置如下:

>java -version
> openjdk version "1.8.0_91"
> OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~15.10.1-b14)
> OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
4

3 回答 3

218

注意:这个答案虽然在技术上是正确的,但现在已经过时了

现在可通过 Android Gradle Plugin 4.0.0+ 获得 Java 8+ API 脱糖支持

(另请参阅下面的 Basil Bourque 的回答

ThreeTenABP 库的开发正在逐渐结束。请考虑在未来几个月内切换到 Android Gradle 插件 4.0、java.time.* 及其核心库脱糖功能。

要在任何版本的 Android 平台上启用对这些语言 API 的支持,请将Android 插件更新到 4.0.0(或更高版本)并在模块的 build.gradle 文件中包含以下内容:

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5'
}

原始答案

第一次发现:为什么必须使用ThreeTenABP而不是java.timeThreeTen-Backport甚至Joda-Time

这是定义新标准的漫长过程的一个非常短的版本。所有这些包几乎都是一样的:为 Java 提供良好、现代的时间处理功能的库。差异是微妙但重要的。

最明显的解决方案是使用内置java.time包,因为这是在 Java 中处理时间和日期的新标准方法。它是JSR 310的实现,它是基于Joda-Time库的时间处理新标准提案。

但是,是在Java 8java.time中引入的。直到Marshmallow的 Android在 Java 7 上运行(“Android N”是第一个引入 Java 8 语言功能的版本)。因此,除非您只针对Android N Nougat及更高版本,否则您不能依赖 Java 8 语言功能(我实际上不确定这是否 100% 正确,但这就是我的理解)。所以出来了。java.time

下一个选项可能是Joda-Time,因为JSR 310基于 Joda-Time。然而,正如ThreeTenABP 自述文件所指出的,出于多种原因,Joda-Time 并不是最佳选择。

接下来是ThreeTen-Backport,它将 Java 8 的大部分(但不是全部)java.time功能向后移植到 Java 7。这对于大多数用例来说都很好,但是正如ThreeTenABP 自述文件中所指出的那样,它在 Android 上存在性能问题。

所以最后一个看似正确的选项是ThreeTenABP

第二个发现:构建工具和依赖管理

由于编译程序——尤其是使用一堆外部库的程序——很复杂,Java 几乎总是使用“构建工具”来管理该过程。MakeApache AntApache MavenGradle都是用于 Java 程序的构建工具(请参阅这篇文章进行比较)。正如下文所述,Gradle 是 Android 项目的首选构建工具。

这些构建工具包括依赖管理。Apache Maven 似乎是第一个包含集中包存储库的。Maven 引入了Maven Central Repository,它允许composer与 Packagist 中的 php 和 ruby​​gems.org 中的 Ruby等效的功能gem。换句话说,Maven Central Repository 之于 Maven(和 Gradle)就像 Packagist 之于 composer —— 版本化包的权威且安全的来源。

第三个发现:Gradle 处理 Android 项目中的依赖关系

在我的待办事项清单上,最重要的是在这里阅读 Gradle 文档,包括他们的免费电子书。如果我在几周前开始学习 Android 时阅读了这些内容,我肯定会知道 Gradle 可以使用 Maven 中央存储库来管理 Android 项目中的依赖项。此外,正如 StackOverflow 答案中所详述的那样,从 Android Studio 0.8.9 开始,Gradle 通过 Bintray 的 JCenter 隐式使用 Maven 中央存储库,这意味着您无需进行任何额外的配置来设置存储库——您只需列出依赖关系。

第四发现:项目依赖列在[project dir]/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 存储库compile 'this-or-that',您会在自述文件的“下载”部分看到那句臭名昭著的行。

当我第一次点击这个 github repo 时,我不知道那个编译行是什么意思,我试图在我的终端中运行它(有一个明显且可预测的失败)。沮丧,直到我弄清楚其余部分很久之后,我才回到它,并最终意识到这是指向com.jakewharton.threetenabprepo 的 Maven Repo 行,而不是org.threetenrepo。这就是为什么我认为 ThreeTenABP 包不在 Maven 存储库中的原因。

总结:让它发挥作用

现在这一切似乎都很容易。通过确保您的[project folder]/app/build.gradle文件implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'在其dependencies部分中包含以下行,您可以在 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'
}

还要将此添加到应用程序类:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
于 2016-08-12T16:36:26.833 回答
13
于 2020-05-05T00:35:59.177 回答
6

在 Android Studio 的构建 gradle(模块级别)文件中添加以下内容:

implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'

创建 Application 类并像这样初始化它:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
于 2019-08-18T17:02:58.770 回答