Verwendung von ThreeTenABP in Android Project

192

Ich stelle diese Frage, weil ich neu in Java und Android bin und stundenlang gesucht habe, um dies herauszufinden. Die Antwort kam aus einer Kombination verwandter Antworten, also dachte ich mir, ich würde dokumentieren, was ich für alle anderen gelernt habe, die möglicherweise Probleme haben. Siehe Antwort.

Ich verwende Android Studio 2.1.2 und mein Java-Setup ist das folgende:

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

Antworten:

192

Achtung: Java 8+ API Desugaring-Unterstützung (Android Gradle Plugin 4.0.0+)

Die Entwicklung dieser Bibliothek ( ThreeTenABP ) wird eingestellt. Bitte erwägen Sie, in den kommenden Monaten auf das Android Gradle-Plugin 4.0, java.time. * Und dessen Kernfunktion zum Entschärfen der Bibliothek umzusteigen.

Aktualisieren Sie das Android-Plugin auf 4.0.0 (oder höher) und fügen Sie Folgendes in die build.gradle-Datei Ihres Moduls ein, um die Unterstützung für diese Sprach-APIs auf jeder Version der Android-Plattform zu aktivieren:

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

Erste Entdeckung: Warum Sie ThreeTenABP anstelle von java.time , ThreeTen-Backport oder sogar Joda-Time verwenden müssen

Dies ist eine wirklich kurze Version des SEHR LANGEN PROZESSES zur Definition eines neuen Standards. Alle diese Pakete sind so ziemlich dasselbe: Bibliotheken, die eine gute, moderne Zeitverarbeitungsfunktion für Java bieten. Die Unterschiede sind subtil, aber wichtig.

Die naheliegendste Lösung wäre die Verwendung des integrierten java.timePakets, da dies die neue Standardmethode für den Umgang mit Zeit und Datum in Java ist. Es handelt sich um eine Implementierung von JSR 310 , einem neuen Standardvorschlag für die Zeitbehandlung auf der Grundlage der Joda-Time- Bibliothek.

Wurde java.timejedoch in Java 8 eingeführt . Android bis Marshmallow läuft unter Java 7 ("Android N" ist die erste Version, die Java 8-Sprachfunktionen einführt). Wenn Sie also nicht nur auf Android N Nougat und höher abzielen , können Sie sich nicht auf Java 8-Sprachfunktionen verlassen (ich bin mir nicht sicher, ob dies zu 100% zutrifft, aber so verstehe ich es). Also java.timeist raus.

Die nächste Option könnte Joda-Time sein , da JSR 310 auf Joda-Time basiert. Wie aus der ThreeTenABP-Readme-Datei hervorgeht, ist Joda-Time aus mehreren Gründen nicht die beste Option.

Als nächstes folgt ThreeTen-Backport , das einen Großteil (aber nicht alle) der Java 8- java.timeFunktionen auf Java 7 zurückportiert . Dies ist für die meisten Anwendungsfälle in Ordnung , weist jedoch, wie in der ThreeTenABP-Readme-Datei angegeben , Leistungsprobleme mit Android auf.

Die letzte und scheinbar richtige Option ist also ThreeTenABP .

Zweite Entdeckung: Build Tools und Abhängigkeitsmanagement

Da das Kompilieren eines Programms - insbesondere eines Programms mit mehreren externen Bibliotheken - komplex ist, verwendet Java fast immer ein "Build-Tool" , um den Prozess zu verwalten. Make , Apache Ant , Apache Maven und Gradle sind Build-Tools, die mit Java-Programmen verwendet werden ( Vergleiche finden Sie in diesem Beitrag ). Wie weiter unten erwähnt, ist Gradle das ausgewählte Build-Tool für Android-Projekte.

Diese Build-Tools umfassen das Abhängigkeitsmanagement. Apache Maven scheint der erste zu sein, der ein zentrales Paket-Repository enthält. Maven führte das Maven Central Repository ein , das Funktionen ermöglicht, die composerPHPs mit Packagist und Rubys gemmit rubygems.org entsprechen. Mit anderen Worten, das Maven Central Repository ist für Maven (und Gradle) das, was Packagist für den Komponisten ist - eine endgültige und sichere Quelle für versionierte Pakete.

Dritte Entdeckung: Gradle behandelt Abhängigkeiten in Android-Projekten

Ganz oben auf meiner To-Do-Liste steht das Lesen der Gradle-Dokumente hier , einschließlich der kostenlosen eBooks. Hätte ich diese Wochen gelesen, als ich anfing, Android zu lernen, hätte ich sicherlich gewusst, dass Gradle das Maven Central Repository verwenden kann, um Abhängigkeiten in Android-Projekten zu verwalten. Wie in dieser StackOverflow-Antwort beschrieben, verwendet Gradle ab Android Studio 0.8.9 implizit das Maven Central Repository über Bintrays JCenter. Dies bedeutet, dass Sie keine zusätzliche Konfiguration vornehmen müssen, um das Repo einzurichten Abhängigkeiten.

Vierte Entdeckung: Projektabhängigkeiten werden in [Projektverzeichnis] ​​/app/build.gradle aufgelistet

Wiederum offensichtlich für diejenigen, die Erfahrung mit Gradle in Java haben, aber ich habe eine Weile gebraucht, um das herauszufinden. Wenn Sie Leute sehen, die "Oh, fügen Sie einfach hinzu compile 'this-or-that.jar'" oder ähnliches sagen, wissen Sie, dass dies compileeine Anweisung in dieser build.gradle-Datei ist, die Abhängigkeiten zur Kompilierungszeit angibt. Hier ist die offizielle Gradle-Seite zum Abhängigkeitsmanagement.

Fünfte Entdeckung: ThreeTenABP wird von Jake Wharton verwaltet, nicht von ThreeTen

Ein weiteres Problem, für das ich zu viel Zeit aufgewendet habe. Wenn Sie in Maven Central nach ThreeTen suchen, werden nur Pakete für angezeigt threetenbp, nicht für threetenabp. Wenn Sie zum Github-Repo für ThreeTenABP gehen , sehen Sie diese berüchtigte compile 'this-or-that'Zeile im Download-Bereich der Readme-Datei.

Als ich dieses Github-Repo zum ersten Mal traf, wusste ich nicht, was diese Kompilierungszeile bedeutete, und versuchte, sie in meinem Terminal auszuführen (mit einem offensichtlichen und vorhersehbaren Fehler). Frustriert kehrte ich erst lange danach zurück, nachdem ich den Rest herausgefunden hatte, und stellte schließlich fest, dass es sich um eine Maven Repo-Linie handelt, die auf das com.jakewharton.threetenabpRepo zeigt, im Gegensatz zum org.threetenRepo. Deshalb dachte ich, das ThreeTenABP-Paket sei nicht im Maven-Repo.

Zusammenfassung: Damit es funktioniert

Jetzt scheint alles ziemlich einfach zu sein. Sie können moderne Zeitverarbeitungsfunktionen in einem Android-Projekt erhalten, indem Sie sicherstellen, dass Ihre [project folder]/app/build.gradleDatei die folgende implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'Zeile enthält 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'
}

Fügen Sie dies auch zur Anwendungsklasse hinzu:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
kael
quelle
1
Danke für den tollen Beitrag. Ich frage mich jedoch, ob Sie auch an JodaTimeAndroid gedacht haben .
Bob
@ Bob, ich habe nicht mit JodaTimeAndroid experimentiert, sondern nur, weil ich gerade nicht wirklich an etwas arbeite, das es erfordert. java.timeSoweit ich mich erinnere, war die Implementierung in Ordnung (im Grunde genommen eine Portierung von JodaTime), und ich bin sicher, dass in ein oder zwei weiteren Jahren 90% der Benutzer auf Nougat + sein werden, was es zu einer praktikablen Lösung für die Entwicklung macht.
Kael
2
@Bob, JodaTime ist im Grunde dasselbe wie JSR-310 (sogar im Grunde genommen von denselben Leuten hergestellt), außer dass JSR-310 angeblich weniger Designfehler aufweist (siehe zum Beispiel diesen Artikel ). [... weiter unten]
M. Prokhorov
2
Um die Kommentare zu verdeutlichen… Das java.time- Framework ( JSR 310 ) ist der offizielle Nachfolger des Joda-Time- Projekts. Beide Projekte werden von Stephen Colebourne geleitet . Das Joda-Time-Projekt befindet sich jetzt im Wartungsmodus. Das Team empfiehlt die Migration zu java.time.
Basil Bourque
6
Stellen Sie sicher , dass Sie anrufen , AndroidThreeTen.init(this)bevor Sie die API verwenden, zum Beispiel in onCreate().Siehe ThreeTen-Backport - Fehler auf Android - ZoneRulesException: keine Zeitzonendatendateien registriert .
Ole VV
5

Die akzeptierte Antwort von kael ist korrekt. Darüber hinaus werde ich einige Dinge erwähnen und ein Diagramm zum Erhalten der Java.time- Funktionalität bereitstellen .

java.time in Android 26+ integriert

Wenn Sie auf Android 26 oder höher abzielen , finden Sie eine Implementierung von JSR 310 ( java.time classes), die mit Android gebündelt ist. ThreeTenABP muss nicht hinzugefügt werden .

APIs nahezu identisch

Zur Verdeutlichung ist ThreeTenABP für Android eine Anpassung der ThreeTen-Backport- Bibliothek, die die meisten Funktionen von java.time auf Java 6 und Java 7 bringt . Dieser Back-Port hat fast die gleiche API wie java.time .

Angenommen, Sie zielen jetzt auf Android vor 26 ab und verwenden ThreeTenABP . Später können Sie möglicherweise die Unterstützung für diese früheren Versionen von Android einstellen , um die mit Android gebündelten Klassen java.time zu verwenden . In diesem Fall müssen Sie nur wenige Änderungen an Ihrer Codebasis vornehmen, außer (a) Schaltanweisungen importund (b) alle Aufrufe, die Sie getätigt haben org.threeten.bp.DateTimeUtils, um die neuen Konvertierungsmethoden zu verwenden, die den alten Datums- / Uhrzeitklassen ( Date, GregorianCalendar) hinzugefügt wurden. .

Der Übergang von ThreeTenABP zu java.time sollte reibungslos und nahezu schmerzfrei sein.

Wann welches Framework zu verwenden ist

Hier ist ein Diagramm, das die drei Frameworks zeigt und angibt, wann welches in welchen Szenarien verwendet werden soll.

Update: Das Android Gradle Plugin 4.0.0+ bietet eine neue vierte Option: API-Desugaring , um eine Teilmenge der Funktionen von java.time verfügbar zu machen, die ursprünglich nicht in früheren Android integriert waren. Siehe oben in der Hauptantwort von kael.

Tabelle, welche java.time-Bibliothek mit welcher Java- oder Android-Version verwendet werden soll


Über java.time

Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie java.util.Date, Calendar, & SimpleDateFormat.

Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .

Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .

Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für java.sql.*Klassen. Hibernate 5 und JPA 2.2 unterstützen java.time .

Woher bekomme ich die java.time-Klassen?

Basil Bourque
quelle
4

Fügen Sie Folgendes in Ihre Build-Gradle-Datei in Android Studio ein.

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

Erstellen Sie die Anwendungsklasse und initialisieren Sie sie wie folgt:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
Richard Kamere
quelle