Cách sử dụng ThreeTenABP trong Dự án Android


192

Tôi đang hỏi câu hỏi này vì tôi mới biết về Java và Android và tôi đã tìm kiếm hàng giờ để cố gắng tìm ra câu hỏi này. Câu trả lời đến từ sự kết hợp của các câu trả lời liên quan, vì vậy tôi đoán rằng tôi sẽ ghi lại những gì tôi học được cho bất kỳ ai khác có thể đang vật lộn. Xem câu trả lời.

Tôi đang sử dụng Android Studio 2.1.2 và thiết lập Java của tôi như sau:

>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)

Câu trả lời:


192

Chú ý: Hỗ trợ giải mã API Java 8+ (Plugin Android Gradle 4.0.0+)

Phát triển trên thư viện này ( ThreeTenABP ) đang đi xuống. Vui lòng xem xét chuyển sang plugin Android Gradle 4.0, java.time. * Và tính năng giải nén thư viện cốt lõi của nó trong những tháng tới.

Để bật hỗ trợ cho các API ngôn ngữ này trên bất kỳ phiên bản nào của nền tảng Android, hãy cập nhật plugin Android lên 4.0.0 (hoặc cao hơn) và bao gồm các phần sau trong tệp build.gradle của mô-đun của bạn:

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'
}

Khám phá đầu tiên: Tại sao bạn phải sử dụng ThreeTenABP thay vì java.time , ThreeTen-Backport hoặc thậm chí là Joda-Time

Đây là một phiên bản thực sự ngắn của QUY TRÌNH RẤT DÀI để xác định một tiêu chuẩn mới. Tất cả các gói này khá giống nhau: các thư viện cung cấp chức năng xử lý thời gian tốt, hiện đại cho Java. Sự khác biệt là tinh tế nhưng quan trọng.

Giải pháp rõ ràng nhất là sử dụng java.timegói tích hợp, vì đây là cách tiêu chuẩn mới để xử lý thời gian và ngày tháng trong Java. Đây là một triển khai của JSR 310 , đây là một đề xuất tiêu chuẩn mới để xử lý thời gian dựa trên thư viện Joda-Time .

Tuy nhiên, java.timeđã được giới thiệu trong Java 8 . Android lên tới Marshmallow chạy trên Java 7 ("Android N" là phiên bản đầu tiên giới thiệu các tính năng ngôn ngữ Java 8). Do đó, trừ khi bạn chỉ nhắm mục tiêu Android N Nougat trở lên, bạn không thể dựa vào các tính năng ngôn ngữ Java 8 (Tôi thực sự không chắc chắn điều này đúng 100%, nhưng đây là cách tôi hiểu về nó). Thế java.timelà hết.

Tùy chọn tiếp theo có thể là Joda-Time , vì JSR 310 dựa trên Joda-Time. Tuy nhiên, như readme ThreeTenABP chỉ ra, vì một số lý do, Joda-Time không phải là lựa chọn tốt nhất.

Tiếp theo là ThreeTen-Backport , vốn hỗ trợ nhiều (nhưng không phải tất cả) java.timechức năng Java 8 cho Java 7. Điều này tốt cho hầu hết các trường hợp sử dụng, nhưng, như đã nêu trong readme ThreeTenABP , nó có vấn đề về hiệu năng với Android.

Vì vậy, tùy chọn cuối cùng và có vẻ đúng là ThreeTenABP .

Khám phá thứ hai: Xây dựng công cụ và quản lý phụ thuộc

Do việc biên dịch một chương trình - đặc biệt là một chương trình sử dụng một loạt các thư viện bên ngoài - rất phức tạp, Java hầu như luôn sử dụng một "công cụ xây dựng" để quản lý quy trình. Make , Apache Ant , Apache MavenGradle đều là các công cụ xây dựng được sử dụng với các chương trình Java (xem bài đăng này để so sánh). Như đã lưu ý thêm, Gradle là công cụ xây dựng được chọn cho các dự án Android.

Những công cụ xây dựng này bao gồm quản lý phụ thuộc. Apache Maven dường như là người đầu tiên bao gồm kho lưu trữ gói tập trung. Maven giới thiệu Kho lưu trữ trung tâm Maven , cho phép chức năng tương đương với php composervới Packagist và Ruby gemvới rubygems.org. Nói cách khác, Kho lưu trữ trung tâm Maven dành cho Maven (và Gradle) Packagist là gì đối với nhà soạn nhạc - một nguồn chính xác và an toàn cho các gói được phiên bản.

Khám phá thứ ba: Gradle Xử lý phụ thuộc trong các dự án Android

Cao trong danh sách việc cần làm của tôi là đọc các tài liệu Gradle ở đây , bao gồm cả ebook miễn phí của họ. Tôi đã đọc những tuần trước khi tôi bắt đầu học Android, tôi chắc chắn sẽ biết rằng Gradle có thể sử dụng Kho lưu trữ trung tâm Maven để quản lý các phụ thuộc trong Dự án Android. Hơn nữa, như chi tiết trong câu trả lời StackOverflow này , kể từ Android Studio 0.8.9, Gradle sử dụng Kho lưu trữ trung tâm của Maven thông qua JCenter của Bintray, có nghĩa là bạn không phải thực hiện bất kỳ cấu hình bổ sung nào để thiết lập repo - bạn chỉ cần liệt kê phụ thuộc.

Khám phá thứ tư: Phụ thuộc dự án được liệt kê trong [dir dự án] /app/build.gradle

Một lần nữa, rõ ràng với những người có bất kỳ kinh nghiệm sử dụng Gradle trong Java, nhưng tôi phải mất một thời gian để tìm ra điều này. Nếu bạn thấy mọi người nói "Ồ, chỉ cần thêm compile 'this-or-that.jar'" hoặc một cái gì đó tương tự, hãy biết rằng đó compilelà một lệnh trong tệp build.gradle chỉ ra các phụ thuộc thời gian biên dịch. Đây là trang Gradle chính thức về quản lý phụ thuộc.

Khám phá thứ năm: ThreeTenABP được quản lý bởi Jake Wharton, không phải bởi ThreeTen

Một vấn đề khác tôi đã dành quá nhiều thời gian để tìm ra. Nếu bạn tìm ThreeTen trong Maven Central, bạn sẽ chỉ thấy các gói cho threetenbpchứ không phảithreetenabp . Nếu bạn đi đến repo github cho ThreeTenABP , bạn sẽ thấy compile 'this-or-that'dòng khét tiếng đó trong phần Tải xuống của Readme.

Khi tôi lần đầu tiên nhấn vào repo github này, tôi không biết dòng biên dịch đó có nghĩa gì và tôi đã cố chạy nó trong thiết bị đầu cuối của mình (với một thất bại rõ ràng và có thể dự đoán được). Thất vọng, tôi đã không trở lại với nó cho đến khi tôi nhận ra phần còn lại, và cuối cùng nhận ra rằng đó là dòng Maven Repo chỉ vào com.jakewharton.threetenabprepo, trái ngược với org.threetenrepo. Đó là lý do tại sao tôi nghĩ gói ThreeTenABP không có trong repo Maven.

Tóm tắt: Làm cho nó hoạt động

Bây giờ tất cả có vẻ khá dễ dàng. Bạn có thể có được các chức năng xử lý thời gian hiện đại trong một dự án Android bằng cách đảm bảo [project folder]/app/build.gradletệp của bạn có implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'dòng trong dependenciesphần của nó :

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'
}

Đồng thời thêm phần này vào lớp Ứng dụng:

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

1
Cảm ơn cho bài viết tuyệt vời. Tuy nhiên, tôi tự hỏi liệu bạn đã xem xét JodaTimeAndroid chưa .
Bob

@Bob, tôi chưa thử nghiệm với JodaTimeAndroid, nhưng chỉ vì tôi không thực sự làm việc với bất cứ điều gì ngay bây giờ mà yêu cầu nó. Theo những gì tôi nhớ, việc java.timetriển khai vẫn ổn (về cơ bản là một cổng của JodaTime) và tôi chắc chắn rằng trong một hoặc hai năm nữa, 90% người dùng sẽ sử dụng Nougat +, biến nó thành một giải pháp khả thi để phát triển.
kael

2
@Bob, JodaTime về cơ bản giống như JSR-310 (thậm chí về cơ bản được tạo ra bởi cùng một kẻ), ngoại trừ JSR-310 được cho là có ít lỗi thiết kế hơn ( ví dụ, xem bài viết này ). [... tiếp tục bên dưới]
M. Prokhorov

2
Để làm rõ các ý kiến, Khung java.time ( JSR 310 ) là sự kế thừa chính thức cho dự án Joda-Time . Cả hai dự án đều được dẫn dắt bởi cùng một người đàn ông, Stephen Colebourne . Dự án Joda-Time hiện đang ở chế độ bảo trì, với nhóm tư vấn di chuyển sang java.time.
Basil Bourque

6
Đảm bảo bạn gọi AndroidThreeTen.init(this)trước khi sử dụng API, ví dụ như trong onCreate().See lỗi ThreeTen-backport trên Android - ZoneRulesException: Không có múi giờ tập tin dữ liệu đã đăng ký .
Ole VV

5

Câu trả lời được chấp nhận bởi kael là chính xác. Ngoài ra, tôi sẽ đề cập đến một vài điều và cung cấp một sơ đồ về việc có được chức năng java.time .

java.time được tích hợp vào Android 26+

Nếu nhắm mục tiêu Android 26 trở lên, bạn sẽ thấy việc triển khai JSR 310 ( các lớp java.time ) đi kèm với Android. Không cần thêm ThreeTenABP .

API gần giống nhau

Chỉ cần làm rõ, ThreeTenABP cho Android là một bản phóng tác của thư viện ThreeTen-Backport mang hầu hết các chức năng java.time cho Java 6Java 7 . Cổng sau này chia sẻ gần như một API giống hệt với java.time .

Giả sử bạn hiện đang nhắm mục tiêu Android sớm hơn 26, vì vậy bạn sử dụng ThreeTenABP . Sau đó, cuối cùng bạn có thể bỏ hỗ trợ cho các phiên bản Android trước đó, để sử dụng các lớp java.time đi kèm với Android. Khi điều đó xảy ra, bạn cần thực hiện một vài thay đổi cho cơ sở mã của mình ngoài (a) các importcâu lệnh chuyển đổi và (b) thay đổi bất kỳ cuộc gọi nào bạn đã thực hiện org.threeten.bp.DateTimeUtilsđể sử dụng các phương thức chuyển đổi mới được thêm vào các lớp thời gian cũ kế thừa ( Date, GregorianCalendar) .

Quá trình chuyển đổi từ ThreeTenABP sang java.time sẽ diễn ra suôn sẻ và gần như không gây đau đớn.

Khi nào nên sử dụng khung nào

Dưới đây là biểu đồ hiển thị ba khung và cho biết khi nào nên sử dụng khung nào trong kịch bản nào.

Cập nhật: Plugin Android Gradle 4.0.0+ mang đến tùy chọn thứ 4 mới, giải nén API để cung cấp một tập hợp con của chức năng java.time ban đầu không được tích hợp vào Android trước đó. Xem đầu câu trả lời chính của kael.

Bảng mà thư viện java.time sẽ sử dụng với phiên bản Java hoặc Android nào


Giới thiệu về java.time

Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian như java.util.Date, Calendar, & SimpleDateFormat.

Để tìm hiểu thêm, xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .

Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.

Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của bạn. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*lớp. Hibernate 5 & JPA 2.2 hỗ trợ java.time .

Nơi để có được các lớp java.time?


4

Thêm phần sau vào tệp lớp xây dựng của bạn trong Android Studio.

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

Tạo lớp Ứng dụng và khởi tạo nó như sau:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.