วิธีใช้ ThreeTenABP ใน Android Project

Aug 12 2016

ฉันถามคำถามนี้เพราะฉันยังใหม่กับ 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)

คำตอบ

200 kael Aug 12 2016 at 23:36

ข้อควรสนใจ: คำตอบนี้แม้ว่าจะถูกต้องในทางเทคนิค แต่ก็ล้าสมัยแล้ว

การสนับสนุน Java 8+ API desugaring พร้อมให้บริการแล้วผ่าน Android Gradle Plugin 4.0.0+

(ดูคำตอบของ Basil Bourque ด้านล่าง )

การพัฒนาบนห้องสมุด ThreeTenABP กำลังสิ้นสุดลง โปรดพิจารณาเปลี่ยนไปใช้ Android Gradle plugin 4.0, java.time. * และคุณลักษณะ desugaring ไลบรารีหลักในอีกไม่กี่เดือนข้างหน้า

หากต้องการเปิดใช้งานการสนับสนุน API ภาษาเหล่านี้บนแพลตฟอร์ม Android เวอร์ชันใดก็ได้ให้อัปเดตปลั๊กอิน 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.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 ได้ (ฉันไม่แน่ใจว่านี่เป็นความจริง 100% แต่นี่คือวิธีที่ฉันเข้าใจ) ดังนั้นจึงjava.timeออก

ตัวเลือกถัดไปอาจเป็นJoda-Timeเนื่องจากJSR 310ขึ้นอยู่กับ Joda-Time อย่างไรก็ตามตามที่ThreeTenABP readmeระบุด้วยเหตุผลหลายประการ Joda-Time ไม่ใช่ตัวเลือกที่ดีที่สุด

ถัดไปคือThreeTen-Backportซึ่งแบ็คพอร์ตมาก (แต่ไม่ใช่ทั้งหมด) ของjava.timeฟังก์ชันJava 8 ไปยัง Java 7 สิ่งนี้ใช้ได้ดีสำหรับกรณีการใช้งานส่วนใหญ่ แต่ตามที่ระบุในการอ่าน ThreeTenABPจะมีปัญหาด้านประสิทธิภาพกับ Android

ดังนั้นที่ผ่านมาและถูกต้องที่ดูเหมือนจะเป็นตัวเลือกที่ThreeTenABP

การค้นพบครั้งที่สอง: สร้างเครื่องมือและการจัดการการพึ่งพา

เนื่องจากการคอมไพล์โปรแกรมโดยเฉพาะโปรแกรมที่ใช้ไลบรารีภายนอกจำนวนมากนั้นมีความซับซ้อน Java จึงแทบจะใช้"เครื่องมือสร้าง"ในการจัดการกระบวนการ Make , Apache Ant , Apache MavenและGradle ล้วนเป็นเครื่องมือสร้างที่ใช้กับโปรแกรม Java (ดูโพสต์นี้สำหรับการเปรียบเทียบ) ดังที่ระบุไว้ต่อไป Gradle เป็นเครื่องมือสร้างที่เลือกสำหรับโครงการ Android

เครื่องมือสร้างเหล่านี้รวมถึงการจัดการการพึ่งพา Apache Maven ดูเหมือนจะเป็นคนแรกที่รวมที่เก็บแพ็กเกจส่วนกลาง Maven เปิดตัวMaven Central Repositoryซึ่งช่วยให้สามารถใช้งานได้เทียบเท่ากับ php composerกับ Packagist และ Ruby gemด้วย rubygems.org กล่าวอีกนัยหนึ่ง Maven Central Repository คือ Maven (และ Gradle) สิ่งที่ Packagist เป็นผู้แต่ง - แหล่งที่มาที่ชัดเจนและปลอดภัยสำหรับแพ็กเกจที่กำหนดเวอร์ชัน

การค้นพบที่สาม: Gradle จัดการการพึ่งพาในโครงการ Android

สิ่งที่ต้องทำของฉันคือการอ่านเอกสาร Gradle ที่นี่รวมถึง eBooks ฟรี หากฉันอ่านเมื่อหลายสัปดาห์ก่อนตอนที่ฉันเริ่มเรียนรู้ Android ฉันก็คงจะรู้อย่างแน่นอนว่า Gradle สามารถใช้ Maven Central Repository เพื่อจัดการการอ้างอิงในโครงการ Android นอกจากนี้ตามรายละเอียดในนี้คำตอบ StackOverflow เป็นของสตูดิโอ Android 0.8.9, Gradle ใช้ Maven กลาง Repository โดยปริยายผ่าน Bintray ของ JCenter ซึ่งหมายความว่าคุณไม่ต้องทำคอนฟิกพิเศษใด ๆ ในการตั้งค่า repo - คุณเพียงแค่รายการ การพึ่งพา

การค้นพบที่สี่: การขึ้นต่อกันของโครงการแสดงอยู่ใน [project dir] /app/build.gradle

เห็นได้ชัดสำหรับผู้ที่มีประสบการณ์ในการใช้ Gradle ใน Java แต่ฉันต้องใช้เวลาสักพักในการคิดออก หากคุณเห็นคนพูดว่า "โอ้แค่เพิ่มcompile 'this-or-that.jar'" หรือคำที่คล้ายกันโปรดทราบว่าcompileเป็นคำสั่งในไฟล์ build.gradle ที่ระบุการอ้างอิงเวลาคอมไพล์ นี่คือหน้า Gradle อย่างเป็นทางการเกี่ยวกับการจัดการการพึ่งพา

การค้นพบที่ห้า: ThreeTenABP ได้รับการจัดการโดย Jake Wharton ไม่ใช่โดย ThreeTen

อีกปัญหาหนึ่งที่ฉันใช้เวลามากเกินไปในการหาคำตอบ ถ้าคุณมองหา ThreeTen ใน Maven กลางคุณจะเห็นเฉพาะแพคเกจสำหรับไม่threetenbp threetenabpหากคุณไปที่github repo สำหรับ ThreeTenABPคุณจะเห็นcompile 'this-or-that'บรรทัดที่น่าอับอายในส่วนดาวน์โหลดของ Readme

เมื่อฉันกด repo github ครั้งแรกฉันไม่รู้ว่าบรรทัดคอมไพล์นั้นหมายถึงอะไรและฉันพยายามเรียกใช้ในเทอร์มินัลของฉัน (ด้วยความล้มเหลวที่ชัดเจนและคาดเดาได้) ผิดหวังฉันไม่ได้กลับไปที่มันจนกว่าฉันจะหาที่เหลือได้ไม่นานและในที่สุดก็รู้ว่ามันเป็นสาย Repo ของ Maven ที่ชี้ไปที่com.jakewharton.threetenabprepo ซึ่งตรงข้ามกับorg.threetenrepo นั่นเป็นเหตุผลที่ฉันคิดว่าแพ็คเกจ ThreeTenABP ไม่ได้อยู่ใน Maven repo

สรุป: ทำให้มันใช้งานได้

ตอนนี้ทุกอย่างดูเหมือนง่ายมาก คุณสามารถรับฟังก์ชันการจัดการเวลาที่ทันสมัยในโครงการ Android ได้โดยตรวจสอบว่า[project folder]/app/build.gradleไฟล์ของคุณมีimplementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'บรรทัดในdependenciesส่วน:

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);
        //...
    }
}
8 BasilBourque May 05 2020 at 07:35

คำตอบที่ยอมรับโดย kaelนั้นถูกต้อง นอกจากนี้ฉันจะพูดถึงสองสิ่งและให้แผนภาพเกี่ยวกับการรับฟังก์ชันjava.time

java.time ในตัว Android 26+

หากกำหนดเป้าหมายเป็นAndroid 26หรือใหม่กว่าคุณจะพบการใช้งานJSR 310 ( คลาสjava.time ) ที่มาพร้อมกับ Android ไม่จำเป็นต้องเพิ่มThreeTenABP

API เกือบจะเหมือนกัน

เพียงชี้แจงThreeTenABPสำหรับ Android คือการปรับตัวของThreeTen-ย้ายกลับห้องสมุดที่นำที่สุดของjava.timeการทำงานเพื่อJava 6และJava 7 แบ่งปันกลับพอร์ตเกือบ API เหมือนกันกับjava.time

สมมติว่าคุณอยู่ในขณะนี้การกำหนดเป้าหมายของ Android ก่อนหน้านี้กว่า 26 เพื่อให้คุณใช้ThreeTenABP ในภายหลังคุณอาจยกเลิกการรองรับ Android เวอร์ชันก่อนหน้านี้เพื่อใช้คลาสjava.time ที่มาพร้อมกับ Android ในกรณีนี้คุณต้องทำการเปลี่ยนแปลงเล็กน้อยใน codebase ของคุณนอกเหนือจาก (a) importคำสั่งการเปลี่ยนและ (b) การเปลี่ยนการโทรใด ๆ ที่คุณทำorg.threeten.bp.DateTimeUtilsเพื่อใช้วิธีการแปลงแบบใหม่ที่เพิ่มลงในคลาสวันที่และเวลาเดิม ( Date, GregorianCalendar) .

กระบวนการเปลี่ยนจากThreeTenABPเป็นjava.timeควรราบรื่นและแทบไม่เจ็บปวด

เมื่อใดควรใช้กรอบงานใด

นี่คือแผนภูมิที่แสดงกรอบงานทั้งสามและระบุว่าเมื่อใดควรใช้กรอบงานใดในสถานการณ์ใด

➥อัปเดต: Android Gradle Plugin 4.0.0+ นำเสนอตัวเลือกที่ 4 ใหม่API desugaringเพื่อให้ใช้งานฟังก์ชันjava.timeส่วนย่อยที่ไม่ได้ติดตั้งไว้ใน Android รุ่นก่อนหน้า ดูด้านบนของคำตอบหลักโดย kael


เกี่ยวกับjava.time

java.timeกรอบถูกสร้างขึ้นใน Java 8 และต่อมา ชั้นเรียนเหล่านี้แย่งลำบากเก่ามรดกเรียนวันที่เวลาเช่นjava.util.Date, และCalendarSimpleDateFormat

ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา Stack Overflow สำหรับตัวอย่างและคำอธิบายมากมาย สเปกJSR 310

โครงการJoda-Timeขณะนี้อยู่ในโหมดการบำรุงรักษาแนะนำการย้ายข้อมูลไปยังคลาสjava.time

คุณสามารถแลกเปลี่ยนวัตถุjava.timeโดยตรงกับฐานข้อมูลของคุณ ใช้ไดรเวอร์ JDBC ที่สอดคล้องกับJDBC 4.2หรือใหม่กว่า ไม่จำเป็นต้องมีสตริงไม่จำเป็นต้องมีjava.sql.*คลาส Hibernate 5 & JPA 2.2 สนับสนุนjava.time

จะหาคลาส java.time ได้ที่ไหน?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11และใหม่กว่า - เป็นส่วนหนึ่งของ Java API มาตรฐานพร้อมการใช้งานแบบรวม
  • Java 9 เพิ่มคุณสมบัติและการแก้ไขเล็กน้อย
  • Java SE 6และ Java SE 7
  • ส่วนใหญ่ของjava.timeการทำงานจะกลับรังเพลิง Java 6 และ 7 ในThreeTen-ย้ายกลับ
  • Android
  • การติดตั้งบันเดิล Android เวอร์ชันที่ใหม่กว่าของคลาสjava.time
  • สำหรับก่อนหน้านี้ Android (<26) ที่ThreeTenABPโครงการปรับThreeTen-ย้ายกลับ (ดังกล่าวข้างต้น) ดูวิธีใช้ ThreeTenABP … .
5 RichardKamere Aug 19 2019 at 00:02

เพิ่มสิ่งต่อไปนี้ในไฟล์ build gradle ของคุณใน Android Studio

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

สร้างคลาสแอปพลิเคชันและเริ่มต้นดังนี้:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}