วิธีใช้ ThreeTenABP ในโครงการ Android


193

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

คำตอบ:


192

ข้อควรสนใจ: การสนับสนุนการเลิกใช้ Java 8+ API (Android Gradle Plugin 4.0.0+)

การพัฒนาในห้องสมุดนี้ ( ThreeTenABP ) กำลังคดเคี้ยว โปรดพิจารณาเปลี่ยนเป็นปลั๊กอิน Android Gradle 4.0, java.time. *, และฟีเจอร์การดึงข้อมูลไลบรารีหลักในอีกไม่กี่เดือนข้างหน้า

ในการเปิดใช้งานการรองรับ 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 readmeนั้นมีปัญหาประสิทธิภาพการทำงานกับ 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) สิ่งที่นักแพ็กเกจใช้ในการแต่งเพลง - แหล่งข้อมูลที่แน่นอนและปลอดภัยสำหรับแพ็คเกจเวอร์ชัน

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

สูงในรายการที่ต้องทำของฉันคือการอ่านเอกสาร Gradle ที่นี่รวมถึง eBooks ฟรีของพวกเขา ถ้าฉันได้อ่านเมื่อหลายสัปดาห์ก่อนตอนนี้ฉันเริ่มเรียนรู้เกี่ยวกับ Android ฉันรู้ว่า Gradle สามารถใช้ Maven Central Repository เพื่อจัดการการอ้างอิงในโครงการ Android ยิ่งไปกว่านั้นตามรายละเอียดในคำตอบ StackOverflow นี้ในขณะที่ Android Studio 0.8.9, Gradle ใช้ Maven Central Repository โดยปริยายผ่าน JCenter ของ Bintray ซึ่งหมายความว่าคุณไม่ต้องทำการตั้งค่าเพิ่มเติมใด ๆ เพื่อตั้งค่า 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หากคุณไปที่repit GitHub สำหรับ ThreeTenABPคุณจะเห็นcompile 'this-or-that'บรรทัดที่น่าอับอายที่อยู่ใต้ส่วนดาวน์โหลดของ Readme

เมื่อฉันตี repo github ครั้งแรกฉันไม่รู้ว่าบรรทัดการคอมไพล์นั้นมีความหมายอย่างไรและฉันพยายามเรียกใช้ในเทอร์มินัลของฉัน (ด้วยความล้มเหลวที่ชัดเจนและคาดเดาได้) ผิดหวังฉันไม่ได้กลับไปจนกว่าจะคิดหาที่เหลือและในที่สุดก็รู้ว่ามันเป็นบรรทัด Maven Repo ชี้ไปที่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);
        //...
    }
}

1
ขอบคุณสำหรับการโพสต์ที่ยอดเยี่ยม อย่างไรก็ตามฉันสงสัยว่าคุณพิจารณาJodaTimeAndroidด้วยหรือไม่
บ๊อบ

@Bob ฉันไม่ได้ทดลองกับ JodaTimeAndroid แต่เพียงเพราะฉันไม่ได้ทำงานอะไรเลยตอนนี้ที่ต้องการมัน จากสิ่งที่ฉันจำได้ว่าการjava.timeติดตั้งใช้งานได้ดี (โดยทั่วไปจะเป็นพอร์ตของ JodaTime) และฉันมั่นใจว่าในอีกหนึ่งหรือสองปีผู้ใช้ 90% จะอยู่ที่ Nougat + ทำให้เป็นโซลูชั่นที่มีศักยภาพสำหรับการพัฒนา
คาเอล

2
@Bob, JodaTime นั้นเหมือนกับ JSR-310 (โดยทั่วไปแล้วจะทำโดยคนเดียวกัน) ยกเว้น JSR-310 ที่มีข้อบกพร่องในการออกแบบน้อยกว่า (ดูตัวอย่างในบทความนี้ ) [... ดำเนินการต่อด้านล่าง]
M. Prokhorov

2
เพื่อชี้แจงความคิดเห็น… กรอบงานjava.time ( JSR 310 ) เป็นผู้สืบทอดอย่างเป็นทางการของโครงการJoda-Time ทั้งสองโครงการจะนำโดยคนคนเดียวกัน, สตีเฟ่น Colebourne ขณะนี้โครงการ Joda-Time อยู่ในโหมดบำรุงรักษาโดยทีมงานให้คำแนะนำเรื่องการย้ายข้อมูลไปยัง java.time
Basil Bourque

6
ให้แน่ใจว่าคุณโทรหาAndroidThreeTen.init(this)ก่อนที่จะใช้ API เช่นในonCreate().See ข้อผิดพลาด ThreeTen-ย้ายกลับบน Android - ZoneRulesException: ไม่มีโซนเวลาไฟล์ข้อมูลที่ลงทะเบียน
Ole VV

5

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

java.timeสร้างขึ้นใน Android 26+

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

APIs เกือบเหมือนกัน

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

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

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

ควรใช้กรอบใด

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

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

ตารางไลบรารี java.time ใดที่จะใช้กับเวอร์ชันของ Java หรือ Android


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

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

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

Joda เวลาโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาให้คำแนะนำแก่การโยกย้ายไปยัง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 … .

4

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

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

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

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.