Jak korzystać z ThreeTenABP w Android Project
Zadaję to pytanie, ponieważ jestem nowy w Javie i Androidzie i szukałem godzin, próbując to rozgryźć. Odpowiedź pochodziła z kombinacji powiązanych odpowiedzi, więc pomyślałem, że udokumentuję to, czego się nauczyłem, dla każdego, kto może mieć problemy. Zobacz odpowiedź.
Używam Android Studio 2.1.2, a moja konfiguracja Java wygląda następująco:
>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)
Odpowiedzi
Uwaga: ta odpowiedź, chociaż technicznie poprawna, jest obecnie nieaktualna
Obsługa desugowania Java 8+ API jest teraz dostępna za pośrednictwem wtyczki Android Gradle 4.0.0+
(Zobacz również odpowiedź Basil Bourque poniżej )
Rozwój biblioteki ThreeTenABP dobiega końca . Proszę rozważyć przejście na wtyczkę Android Gradle 4.0, java.time. * I funkcję usuwania cugry z podstawowej biblioteki w nadchodzących miesiącach.
Aby włączyć obsługę tych językowych interfejsów API w dowolnej wersji platformy Android, zaktualizuj wtyczkę systemu Android do wersji 4.0.0 (lub nowszej) i dołącz następujące elementy do pliku build.gradle modułu:
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'
}
Oryginalna odpowiedź
Pierwsze odkrycie: dlaczego musisz używać ThreeTenABP zamiast java.time , ThreeTen-Backport , a nawet Joda-Time
To jest naprawdę krótka wersja BARDZO DŁUGIEGO PROCESU definiowania nowego standardu. Wszystkie te pakiety to prawie to samo: biblioteki, które zapewniają dobrą, nowoczesną obsługę języka Java. Różnice są subtelne, ale ważne.
Najbardziej oczywistym rozwiązaniem byłoby użycie wbudowanego java.time
pakietu, ponieważ jest to nowy standardowy sposób radzenia sobie z czasem i datami w Javie. Jest to implementacja JSR 310 , która była nową standardową propozycją obsługi czasu opartą o bibliotekę Joda-Time .
Jednak java.time
został wprowadzony w Javie 8 . Android do Marshmallow działa na Javie 7 („Android N” jest pierwszą wersją, która wprowadza funkcje językowe Java 8). Tak więc, jeśli nie celujesz tylko w system Android N Nougat i nowszy, nie możesz polegać na funkcjach językowych Java 8 (nie jestem pewien, czy to w 100% prawda, ale tak to rozumiem). Więc java.time
jest na zewnątrz.
Następną opcją może być Joda-Time , ponieważ JSR 310 był oparty na Joda-Time. Jednak, jak wskazuje plik Readme ThreeTenABP , z wielu powodów Joda-Time nie jest najlepszą opcją.
Następny jest ThreeTen-Backport , który przenosi wiele (ale nie wszystkie) funkcjonalności Java 8 java.time
do Java 7. Jest to w porządku w większości przypadków użycia, ale, jak wskazano w pliku Readme ThreeTenABP , ma problemy z wydajnością w systemie Android.
Więc ostatnią i pozornie poprawną opcją jest ThreeTenABP .
Drugie odkrycie: narzędzia budowania i zarządzanie zależnościami
Ponieważ kompilowanie programu - zwłaszcza takiego, który wykorzystuje kilka bibliotek zewnętrznych - jest skomplikowane, Java prawie zawsze używa „narzędzia do budowania” do zarządzania tym procesem. Make , Apache Ant , Apache Maven i Gradle to narzędzia do budowania, które są używane z programami Java (zobacz ten post w celu porównania). Jak wspomniano poniżej, Gradle jest wybranym narzędziem do kompilacji projektów dla systemu Android.
Te narzędzia do kompilacji obejmują zarządzanie zależnościami. Wydaje się, że Apache Maven jako pierwszy zawiera scentralizowane repozytorium pakietów. Maven wprowadził Maven Central Repository , które zapewnia funkcjonalność równoważną php composer
z Packagist i Ruby's gem
z rubygems.org. Innymi słowy, Maven Central Repository jest dla Mavena (i Gradle'a) tym, czym Packagist dla kompozytora - ostatecznym i bezpiecznym źródłem pakietów wersjonowanych.
Trzecie odkrycie: Gradle obsługuje zależności w projektach systemu Android
Wysoko na mojej liście rzeczy do zrobienia jest, aby przeczytać Gradle docs tutaj , w tym ich książek gratis. Gdybym czytał kilka tygodni temu, kiedy zacząłem uczyć się Androida, z pewnością wiedziałbym, że Gradle może używać Maven Central Repository do zarządzania zależnościami w projektach Androida. Ponadto, jak opisano szczegółowo w tej odpowiedzi StackOverflow, od wersji Android Studio 0.8.9, Gradle używa Maven Central Repository niejawnie za pośrednictwem JCenter Bintray, co oznacza, że nie musisz wykonywać żadnej dodatkowej konfiguracji, aby skonfigurować repozytorium - wystarczy wymienić zależności.
Czwarte odkrycie: Zależności projektu są wymienione w [katalog projektu] /app/build.gradle
Ponownie, oczywiste dla tych, którzy mają jakiekolwiek doświadczenie w używaniu Gradle w Javie, ale zajęło mi trochę czasu, zanim to zrozumiałem. Jeśli zobaczysz, że ludzie mówią „Och, po prostu dodaj compile 'this-or-that.jar'
” lub coś podobnego, wiedz, że compile
jest to dyrektywa w tym pliku build.gradle, która wskazuje na zależności w czasie kompilacji. Oto oficjalna strona Gradle dotycząca zarządzania zależnościami.
Piąte odkrycie: ThreeTenABP jest zarządzane przez Jake'a Whartona, a nie przez ThreeTen
Kolejna kwestia, nad którą spędziłem zbyt dużo czasu, zastanawiała się. Jeśli szukasz ThreeTen w Maven Central, zobaczysz tylko pakiety threetenbp
, a nie threetenabp
. Jeśli przejdziesz do repozytorium ThreeTenABP na githubie , zobaczysz ten niesławny compile 'this-or-that'
wiersz w sekcji pobierania pliku Readme.
Kiedy po raz pierwszy trafiłem na to repozytorium github, nie wiedziałem, co oznacza ten wiersz kompilacji, i próbowałem go uruchomić na moim terminalu (z oczywistą i przewidywalną awarią). Sfrustrowany, wróciłem do tego dopiero długo po tym, jak wymyśliłem resztę i w końcu zdałem sobie sprawę, że to linia Maven Repo wskazująca na com.jakewharton.threetenabp
repozytorium, a nie org.threeten
repozytorium. Dlatego pomyślałem, że pakiet ThreeTenABP nie znajduje się w repozytorium Maven.
Podsumowanie: Jak to działa
Teraz wszystko wydaje się całkiem proste. Możesz uzyskać nowoczesne funkcje obsługi czasu w projekcie systemu Android, upewniając się, że [project folder]/app/build.gradle
plik ma implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
linię w dependencies
sekcji:
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'
}
Dodaj to również do klasy Application:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
AndroidThreeTen.init(this);
//...
}
}
Przyjęta odpowiedź przez kael jest poprawna. Ponadto wspomnę o kilku rzeczach i przedstawię diagram dotyczący uzyskiwania funkcjonalności java.time .
java.time wbudowany w Androida 26+
W przypadku systemu Android 26 lub nowszego znajdziesz implementację JSR 310 ( klasy java.time ) w pakiecie z systemem Android. Nie ma potrzeby dodawania ThreeTenABP .
API prawie identyczne
Gwoli wyjaśnienia, ThreeTenABP na Androida to adaptacja biblioteki ThreeTen-Backport, która przenosi większość funkcji java.time do Java 6 i Java 7 . Ten tylny port ma prawie identyczny interfejs API z java.time .
Załóżmy, że celujesz teraz w system Android starszy niż 26 lat, więc używasz ThreeTenABP . Później możesz ostatecznie zrezygnować z obsługi tych wcześniejszych wersji Androida, aby korzystać z klas java.time dołączonych do Androida. Kiedy tak się stanie, musisz wprowadzić kilka zmian w bazie kodu innych niż (a) import
instrukcje przełączania i (b) zmiana wszelkich wywołań, które wykonałeś, org.threeten.bp.DateTimeUtils
aby użyć nowych metod konwersji, które zostały dodane do starych klas daty i godziny ( Date
, GregorianCalendar
) .
Proces przejścia z ThreeTenABP do java.time powinien być płynny i prawie bezbolesny.
Kiedy używać którego frameworka
Oto wykres przedstawiający trzy struktury i wskazujący, kiedy użyć której z nich, w jakich scenariuszach.
➥ Aktualizacja: wtyczka Android Gradle 4.0.0+ wprowadza nową czwartą opcję, desugering API, aby udostępnić podzbiór funkcji java.time, które nie były pierwotnie wbudowane we wcześniejszy system Android. Zobacz górę głównej odpowiedzi kaela.
Informacje o java.time
Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak java.util.Date
, Calendar
, i SimpleDateFormat
.
Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .
Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .
Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani java.sql.*
klas. Hibernate 5 i JPA 2.2 obsługują java.time .
Skąd wziąć klasy java.time?
- Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 i nowsze - Część standardowego interfejsu API języka Java z dołączoną implementacją.
- Java 9 dodaje kilka drobnych funkcji i poprawek.
- Java SE 6 i Java SE 7
- Większość funkcji java.time jest przenoszona z powrotem do Java 6 i 7 w ThreeTen-Backport .
- Android
- Późniejsze wersje implementacji klas java.time w pakietach Androida .
- Dla wcześniejszej Androida (<26), ThreeTenABP projekt dostosowuje ThreeTen-backportu (jak wyżej). Zobacz Jak używać ThreeTenABP… .
Dodaj następujące elementy w pliku gradle kompilacji w Android Studio.
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
Utwórz klasę Application i zainicjuj ją w następujący sposób:
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}