วิธีใช้ ThreeTenABP ใน Android Project
ฉันถามคำถามนี้เพราะฉันยังใหม่กับ 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)
คำตอบ
ข้อควรสนใจ: คำตอบนี้แม้ว่าจะถูกต้องในทางเทคนิค แต่ก็ล้าสมัยแล้ว
การสนับสนุน 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.threetenabp
repo ซึ่งตรงข้ามกับorg.threeten
repo นั่นเป็นเหตุผลที่ฉันคิดว่าแพ็คเกจ 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);
//...
}
}
คำตอบที่ยอมรับโดย 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
, และCalendar
SimpleDateFormat
ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา 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 … .
เพิ่มสิ่งต่อไปนี้ในไฟล์ build gradle ของคุณใน Android Studio
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
สร้างคลาสแอปพลิเคชันและเริ่มต้นดังนี้:
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}