Jak korzystać z ThreeTenABP w Android Project

193

Zadaję to pytanie, ponieważ jestem nowy w Javie i Androidzie i szukałem godzin, próbując to rozgryźć. Odpowiedź pochodzi 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 Androida Studio 2.1.2, a moja konfiguracja Java jest następująca:

>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)
kael
źródło

Odpowiedzi:

192

Uwaga: wsparcie usuwania API Java 8+ (Android Gradle Plugin 4.0.0+)

Rozwój tej biblioteki ( ThreeTenABP ) kończy się. Zastanów się nad przejściem na wtyczkę Android Gradle 4.0, java.time. * I jej podstawową funkcję usuwania bibliotek w nadchodzących miesiącach.

Aby włączyć obsługę tych interfejsów API języka w dowolnej wersji platformy Android, zaktualizuj wtyczkę Androida 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'
}

Pierwsze odkrycie: dlaczego musisz użyć ThreeTenABP zamiast java.time , ThreeTen-Backport , a nawet Joda-Time

To jest naprawdę krótka wersja BARDZO DŁUGIEGO PROCESU zdefiniowania nowego standardu. Wszystkie te pakiety są prawie takie same: biblioteki, które zapewniają dobrą, nowoczesną funkcjonalność obsługi czasu dla Javy. Różnice są subtelne, ale ważne.

Najbardziej oczywistym rozwiązaniem byłoby użycie wbudowanego java.timepakietu, 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ą do obsługi czasu opartą na bibliotece Joda-Time .

Jednak java.timezostał wprowadzony w Javie 8 . Android do Marshmallow działa na Javie 7 („Android N” to pierwsza wersja, która wprowadza funkcje językowe Java 8). Dlatego, chyba że celujesz tylko w Android Nougat i wyżej, nie możesz polegać na funkcjach językowych Java 8 (nie jestem pewien, czy to w 100% prawda, ale tak to rozumiem). Tak java.timejest.

Następną opcją może być Joda-Time , ponieważ JSR 310 był oparty na Joda-Time. Jednak, jak wskazuje readme ThreeTenABP , z wielu powodów Joda-Time nie jest najlepszą opcją.

Dalej jest ThreeTen-Backport , który obsługuje wiele (ale nie wszystkie) środowiska Java 8java.time do Java 7. Jest to dobre w większości przypadków użycia, ale, jak wskazano w pliku ReadTeTABABP , ma problemy z wydajnością w Androidzie.

Ostatnią i na pozór poprawną opcją jest ThreeTenABP .

Drugie odkrycie: narzędzia do budowania i zarządzania zależnościami

Ponieważ kompilacja programu - szczególnie korzystającego z wielu zewnętrznych bibliotek - jest złożona, Java prawie zawsze używa „narzędzia do budowania” do zarządzania procesem. Make , Apache Ant , Apache Maven i Gradle są narzędziami do budowania, które są używane z programami Java (zobacz porównania w tym poście ). Jak wspomniano w dalszej części, Gradle to wybrane narzędzie do kompilacji projektów Android.

Te narzędzia do budowania obejmują zarządzanie zależnościami. Wydaje się, że Apache Maven jako pierwszy zawiera scentralizowane repozytorium pakietów. Maven wprowadził Centralne repozytorium Maven , które umożliwia funkcjonalność równoważną php composerz Packagist i Ruby gemz rubygems.org. Innymi słowy, Centralne repozytorium Maven jest dla Maven (i Gradle) tym, czym dla kompozytora jest Packagist - ostateczne i bezpieczne źródło wersjonowanych pakietów.

Trzecie odkrycie: Gradle obsługuje zależności w projektach na Androida

Na mojej liście rzeczy do zrobienia jest przeczytanie dokumentów Gradle tutaj , w tym ich bezpłatnych eBooków. Gdybym przeczytał te tygodnie temu, kiedy zacząłem uczyć się Androida, z pewnością wiedziałbym, że Gradle może używać Centralnego repozytorium Maven do zarządzania zależnościami w projektach na Androida. Ponadto, zgodnie z opisem w tym StackOverflow odpowiedź, jak Android Studio 0.8.9, Gradle używa Maven Centralne Repozytorium pośrednio poprzez Bintray za JCenter, co oznacza, że nie trzeba robić żadnych dodatkowych config Aby skonfigurować repo - wystarczy podać wykaz zależności.

Czwarte odkrycie: Zależności projektu są wymienione w [katalog projektu] /app/build.gradle

Znów, oczywiste dla tych, którzy mają jakiekolwiek doświadczenie w korzystaniu z Gradle w Javie, ale zajęło mi to trochę czasu, aby to zrozumieć. Jeśli widzisz ludzi mówiących „Och, po prostu dodaj compile 'this-or-that.jar'” lub coś podobnego, wiedz, że compilejest to dyrektywa w tym pliku build.gradle, która wskazuje zależności od czasu kompilacji. Oto oficjalna strona Gradle na temat zarządzania zależnościami.

Piąte odkrycie: ThreeTenABP zarządza Jake Wharton, a nie ThreeTen

Jeszcze jedna kwestia, którą spędziłem zbyt długo, zastanawiając się. Jeśli szukasz ThreeTen w Maven Central, zobaczysz tylko pakiety threetenbp, a nie threetenabp. Jeśli przejdziesz do repozytorium github dla ThreeTenABP , zobaczysz tę niesławną compile 'this-or-that'linię w sekcji Pobieranie Readme.

Kiedy po raz pierwszy uderzyłem w repozytorium github, nie wiedziałem, co oznacza ta linia kompilacji, i próbowałem uruchomić ją w moim terminalu (z oczywistą i przewidywalną awarią). Sfrustrowany, nie wróciłem do tego długo po tym, jak wymyśliłem resztę, i w końcu zdałem sobie sprawę, że jest to linia Maven Repo wskazująca na com.jakewharton.threetenabprepo, w przeciwieństwie do org.threetenrepo. Dlatego myślałem, że pakietu ThreeTenABP nie ma w repozytorium Maven.

Podsumowanie: Sprawienie, by działało

Teraz wszystko wydaje się dość łatwe. Możesz uzyskać nowoczesne funkcje obsługi czasu w projekcie Android, upewniając się, że [project folder]/app/build.gradleplik ma implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'linię w swojej dependenciessekcji:

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 aplikacji:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
kael
źródło
1
Dzięki za świetny post. Zastanawiam się jednak, czy rozważałeś również JodaTimeAndroid .
Bob
@ Bob, nie eksperymentowałem z JodaTimeAndroid, ale tylko dlatego, że tak naprawdę nie pracuję nad niczym, co wymaga tego. Z tego, co pamiętam, java.timewdrożenie było w porządku (jest to po prostu port JodaTime) i jestem pewien, że za rok lub dwa 90% użytkowników będzie korzystało z Nougat +, co czyni go realnym rozwiązaniem dla programistów.
kael
2
@ Bob, JodaTime jest w zasadzie taki sam jak JSR-310 (nawet zasadniczo wykonany przez tych samych facetów), z tym wyjątkiem, że JSR-310 ma prawdopodobnie mniej wad projektowych (patrz na przykład ten artykuł ). [... ciąg dalszy poniżej]
M. Prochorow
2
Aby wyjaśnić komentarze… Framework java.time ( JSR 310 ) jest oficjalnym następcą projektu Joda-Time . Oba projekty są prowadzone przez tego samego człowieka, Stephena Colebourne . Projekt Joda-Time jest teraz w trybie konserwacji, a zespół doradza migrację do java.time.
Basil Bourque,
6
Pamiętaj, aby zadzwonić AndroidThreeTen.init(this)przed użyciem interfejsu API, na przykład w. Zobacz onCreate()błąd ThreeTen-Backport na Androidzie - ZoneRulesException: Brak plików danych strefy czasowej .
Ole VV
5

Akceptowana odpowiedź kael jest poprawna. Ponadto wspomnę o kilku rzeczach i przedstawię schemat uzyskiwania funkcjonalności java.time .

java.time wbudowany w Androida 26+

Jeśli celujesz w Androida 26 lub nowszy, znajdziesz implementację JSR 310 ( klasy java.time ) w pakiecie z Androidem. Nie trzeba dodawać ThreeTenABP .

Interfejsy API prawie identyczne

Aby wyjaśnić, ThreeTenABP dla Androida to adaptacja biblioteki ThreeTen-Backport, która zapewnia większość funkcji java.time w Javie 6 i Java 7 . Ten port tylny ma prawie identyczne API z java.time .

Załóżmy, że celujesz w Androida wcześniej niż 26, więc używasz ThreeTenABP . Później możesz ostatecznie zrezygnować z obsługi wcześniejszych wersji Androida, aby korzystać z klas java.time dołączonych do Androida. Kiedy tak się dzieje, musisz wprowadzić kilka zmian w bazie kodu oprócz (a) importinstrukcji przełączających i (b) zmienić wszelkie wywołania, org.threeten.bp.DateTimeUtilsaby użyć nowych metod konwersji, które zostały dodane do starych klas daty i czasu ( Date, GregorianCalendar) .

Proces przejścia z ThreeTenABP do java.time powinien przebiegać płynnie i prawie bezboleśnie.

Kiedy korzystać z których ram

Oto wykres przedstawiający trzy frameworki i wskazujący, kiedy użyć, w którym scenariuszu.

➥ Aktualizacja: Android Gradle Plugin 4.0.0+ wprowadza nową czwartą opcję, API usuwające, aby udostępnić podzbiór funkcji java.time, która nie była pierwotnie wbudowana we wcześniejszy Android. Zobacz górę głównej odpowiedzi autor: kael.

Tabela, z której biblioteki java.time należy korzystać, w której wersji Java lub Android


O java.time

Środowisko java.time jest wbudowane w Javę 8 i nowsze wersje . 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 stos przepełnienia dla wielu przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Projekt Joda-Time , teraz w trybie konserwacji , zaleca migrację do klas java.time .

Możesz wymienić java.time obiekty bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie potrzeba ciągów, nie ma potrzeby java.sql.*klas. Hibernacja 5 i JPA 2.2 obsługują java.time .

Gdzie można uzyskać klasy java.time?

Basil Bourque
źródło
4

Dodaj następujące elementy do pliku stopni kompilacji w Android Studio.

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

Utwórz klasę aplikacji i zainicjuj ją w następujący sposób:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
Richard Kamere
źródło