如何在Android Project中使用ThreeTenABP


192

我问这个问题是因为我是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)

Answers:


192

注意:Java 8+ API终止代理支持(Android Gradle Plugin 4.0.0+)

这个库(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.time是在Java 8中引入的。高达棉花糖的 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功能反向移植Java7。这对于大多数用例来说都很好,但是,正如ThreeTenABP自述文件所述,它在Android上存在性能问题。

因此,最后一个看似正确的选项是ThreeTenABP

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

由于编译程序(尤其是使用一堆外部库的程序)非常复杂,因此Java几乎总是使用“构建工具”来管理程序。MakeApache AntApache MavenGradle都是与Java程序一起使用的构建工具(请参阅本帖子以进行比较)。如后面所述,Gradle是Android项目的首选构建工具。

这些构建工具包括依赖项管理。Apache Maven似乎是第一个包含集中式软件包存储库的仓库。Maven引入了Maven中央存储库,该允许composer使用与Packagist的php 和gemrubygems.org的Ruby 等效的功能。换句话说,Maven中央存储库是Maven(和Gradle)对Packagist的构想,它是版本包的权威性和安全性来源。

第三次发现:Android项目中的Gradle处理依赖项

在我的待办事项清单中,最重要的是在此处阅读Gradle文档,包括其免费电子书。如果这些星期前我开始学习Android时就读过,那么我肯定会知道Gradle可以使用Maven Central信息库来管理Android项目中的依赖项。此外,正如此 StackOverflow答案中所详述的那样,从Android Studio 0.8.9开始,Gradle通过Bintray的JCenter隐式使用Maven Central Repository,这意味着您不必做任何额外的配置即可设置存储库-您只需列出依赖性。

第四个发现:项目依赖性在[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。如果转到ThreeTenABPgithub存储库,您将compile 'this-or-that'在自述文件的“下载”部分看到该臭名昭著的行。

当我第一次访问此github存储库时,我不知道该编译行的含义,因此我尝试在终端中运行它(出现明显且可预测的故障)。沮丧的是,直到弄清其余部分后,我才回到很长一段时间,最后才意识到这是指向com.jakewharton.threetenabp回购协议的Maven回购协议行,而不是org.threeten回购协议。这就是为什么我认为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'
}

还将其添加到Application类:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}

1
感谢您的精彩帖子。但是,我想知道您是否也考虑过JodaTimeAndroid
鲍勃(Bob)

@Bob,我还没有尝试过JodaTimeAndroid,但这只是因为我现在还没有真正从事任何需要它的工作。据我java.time所知,该实现很好(基本上是JodaTime的移植端口),而且我敢肯定,再过一两年,90%的用户将使用Nougat +,这使其成为可行的开发解决方案。
kael

2
@ Bob,JodaTime与JSR-310基本相同(甚至基本上由同一个人制造),只是JSR-310的设计缺陷较少(例如,请参见本文)。[...下续]
M. Prokhorov

2
为了澄清评论…… java.time框架(JSR 310)是Joda-Time项目的正式继承者。这两个项目均由同一个人Stephen Colebourne领导。Joda-Time项目现在处于维护模式,团队建议迁移到java.time。
罗勒·布尔克

6
请务必与AndroidThreeTen.init(this)使用API之前,例如在onCreate()。看到ThreeTen-反向移植错误在Android上- ZoneRulesException:未注册的时区数据文件
Ole VV

5

kael接受的答案是正确的。另外,我将提到几件事,并提供有关获取java.time功能的图表。

java.time内置的Android 26+

如果定位到Android 26或更高版本,则将发现与Android捆绑在一起的JSR 310java.time类)的实现。无需添加ThreeTenABP

API几乎完全相同

只是为了澄清,ThreeTenABP为Android是一个适应ThreeTen,反向移植库,它带来的大部分java.time功能的Java 6Java 7中。该反向端口与java.time几乎共享相同的API 。

假设您现在定位的Android版本早于26,因此您使用ThreeTenABP。稍后,您可能最终放弃对这些早期版本的Android的支持,以使用与Android捆绑在一起的java.time类。当发生这种情况,你需要做出比其他你的代码一些变化(一)开关import语句,以及(b)改变你做出的任何调用org.threeten.bp.DateTimeUtils使用被添加到旧的遗留日期时间类,新的转换方法(DateGregorianCalendar) 。

ThreeTenABPjava.time的过渡过程应该是平稳且几乎没有痛苦的。

何时使用哪个框架

这是一个图表,显示了这三个框架,并指示了在哪种情况下何时使用哪个框架。

更新: Android Gradle Plugin 4.0.0+引入了第4个新选项,即API desugaring API,以提供最初不是早期Android内置java.time功能子集。参见kael 主要答案的顶部。

哪个版本的Java或Android使用哪个java.time库的表


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。Hibernate 5和JPA 2.2支持java.timejava.sql.*

在哪里获取java.time类?


4

在Android Studio的构建gradle文件中添加以下内容。

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

创建Application类并初始化它,如下所示:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.