Comment utiliser ThreeTenABP dans un projet Android

193

Je pose cette question parce que je suis nouveau sur Java et Android et j'ai cherché pendant des heures à essayer de comprendre cela. La réponse provenait d'une combinaison de réponses connexes, alors j'ai pensé que je documenterais ce que j'avais appris pour quiconque pourrait avoir des difficultés. Voir la réponse.

J'utilise Android Studio 2.1.2 et ma configuration Java est la suivante:

>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
la source

Réponses:

192

Attention: prise en charge du désugarage de l'API Java 8+ (Android Gradle Plugin 4.0.0+)

Le développement de cette bibliothèque ( ThreeTenABP ) s'achève . Veuillez envisager de passer au plugin Android Gradle 4.0, java.time. *, Et à sa fonction de désugarage de bibliothèque principale dans les mois à venir.

Pour activer la prise en charge de ces API de langage sur n'importe quelle version de la plate-forme Android, mettez à jour le plug-in Android vers la version 4.0.0 (ou supérieure) et incluez les éléments suivants dans le fichier build.gradle de votre module:

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

Première découverte: pourquoi vous devez utiliser ThreeTenABP au lieu de java.time , ThreeTen-Backport ou même Joda-Time

Il s'agit d'une version très courte du TRES LONG PROCESSUS de définition d'un nouveau standard. Tous ces packages sont à peu près la même chose: des bibliothèques qui fournissent de bonnes fonctionnalités modernes de gestion du temps pour Java. Les différences sont subtiles mais importantes.

La solution la plus évidente serait d'utiliser le java.timepackage intégré, car il s'agit de la nouvelle manière standard de gérer l'heure et les dates en Java. Il s'agit d'une implémentation de JSR 310 , qui était une nouvelle proposition standard de gestion du temps basée sur la bibliothèque Joda-Time .

Cependant, a java.timeété introduit dans Java 8 . Android jusqu'à Marshmallow fonctionne sur Java 7 ("Android N" est la première version à introduire les fonctionnalités du langage Java 8). Ainsi, à moins que vous ne cibliez uniquement Android N Nougat et supérieur, vous ne pouvez pas vous fier aux fonctionnalités du langage Java 8 (je ne suis pas sûr que ce soit vrai à 100%, mais c'est ainsi que je le comprends). Ainsi java.timeest sorti.

La prochaine option pourrait être Joda-Time , puisque JSR 310 était basé sur Joda-Time. Cependant, comme l' indique le fichier readme de ThreeTenABP , pour un certain nombre de raisons, Joda-Time n'est pas la meilleure option.

Vient ensuite ThreeTen-Backport , qui transfère une grande partie (mais pas la totalité) des java.timefonctionnalités de Java 8 vers Java 7. Cela convient à la plupart des cas d'utilisation, mais, comme indiqué dans le fichier readme de ThreeTenABP , il a des problèmes de performances avec Android.

Donc, la dernière option et apparemment correcte est ThreeTenABP .

Deuxième découverte: outils de création et gestion des dépendances

Comme la compilation d'un programme - en particulier celui qui utilise un tas de bibliothèques externes - est complexe, Java utilise presque invariablement un "outil de construction" pour gérer le processus. Make , Apache Ant , Apache Maven et Gradle sont tous des outils de construction utilisés avec les programmes Java (voir cet article pour des comparaisons). Comme indiqué plus bas, Gradle est l'outil de construction choisi pour les projets Android.

Ces outils de construction incluent la gestion des dépendances. Apache Maven semble être le premier à inclure un référentiel de packages centralisé. Maven a introduit le référentiel central Maven , qui permet des fonctionnalités équivalentes à php composeravec Packagist et Ruby gemavec rubygems.org. En d'autres termes, le référentiel central de Maven est pour Maven (et Gradle) ce que Packagist est pour composer - une source définitive et sécurisée pour les packages versionnés.

Troisième découverte: Gradle gère les dépendances dans les projets Android

Le haut de ma liste de choses à faire est de lire les documents Gradle ici , y compris leurs livres électroniques gratuits. Si j'avais lu ces semaines quand j'ai commencé à apprendre Android, j'aurais sûrement su que Gradle peut utiliser le référentiel central Maven pour gérer les dépendances dans les projets Android. En outre, comme détaillé dans cette réponse StackOverflow, à partir d'Android Studio 0.8.9, Gradle utilise implicitement le référentiel central Maven via JCenter de Bintray, ce qui signifie que vous n'avez pas à faire de configuration supplémentaire pour configurer le dépôt - vous listez simplement le dépendances.

Quatrième découverte: les dépendances du projet sont répertoriées dans [répertoire du projet] /app/build.gradle

Encore une fois, évident pour ceux qui ont une expérience de l'utilisation de Gradle en Java, mais il m'a fallu un certain temps pour comprendre cela. Si vous voyez des gens dire "Oh, ajoutez simplement compile 'this-or-that.jar'" ou quelque chose de similaire, sachez que compilec'est une directive dans ce fichier build.gradle qui indique les dépendances au moment de la compilation. Voici la page officielle Gradle sur la gestion des dépendances.

Cinquième découverte: ThreeTenABP est géré par Jake Wharton, pas par ThreeTen

Encore un autre problème que j'ai passé trop de temps à résoudre. Si vous recherchez ThreeTen dans Maven Central, vous ne verrez que les packages pour threetenbp, pas threetenabp. Si vous accédez au référentiel github pour ThreeTenABP , vous verrez cette infâme compile 'this-or-that'ligne sous la section Télécharger du fichier Lisez-moi.

Quand j'ai frappé pour la première fois ce repo github, je ne savais pas ce que signifiait cette ligne de compilation et j'ai essayé de l'exécuter dans mon terminal (avec un échec évident et prévisible). Frustré, je n'y suis retourné que longtemps après avoir compris le reste et j'ai finalement réalisé qu'il s'agissait d'une ligne Maven Repo pointant vers le com.jakewharton.threetenabprepo, par opposition au org.threetenrepo. C'est pourquoi je pensais que le package ThreeTenABP n'était pas dans le repo Maven.

Résumé: faire fonctionner

Maintenant, tout semble assez facile. Vous pouvez obtenir des fonctions de gestion des temps modernes dans un projet Android en vous assurant que votre [project folder]/app/build.gradlefichier a la implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'ligne dans sa dependenciessection:

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

Ajoutez également ceci à la classe Application:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
Kael
la source
1
Merci pour le super message. Cependant, je me demande si vous avez également envisagé JodaTimeAndroid .
Bob
@Bob, je n'ai pas expérimenté JodaTimeAndroid, mais uniquement parce que je ne travaille pas vraiment sur quoi que ce soit qui le nécessite. D'après ce dont je me souviens, la java.timemise en œuvre était correcte (étant essentiellement un portage de JodaTime), et je suis sûr que dans un an ou deux, 90% des utilisateurs seront sur Nougat +, ce qui en fait une solution viable pour le développement.
kael
2
@Bob, JodaTime est fondamentalement le même que JSR-310 (même fondamentalement fabriqué par les mêmes gars), sauf que JSR-310 a supposément moins de défauts de conception (voir cet article , par exemple). [... suite ci-dessous]
M. Prokhorov
2
Pour clarifier les commentaires… Le framework java.time ( JSR 310 ) est le successeur officiel du projet Joda-Time . Les deux projets sont dirigés par le même homme, Stephen Colebourne . Le projet Joda-Time est maintenant en mode maintenance, l'équipe conseillant la migration vers java.time.
Basil Bourque
6
Assurez-vous d'appeler AndroidThreeTen.init(this)avant d'utiliser l'API, par exemple dans onCreate().See ThreeTen-Backport error on Android - ZoneRulesException: No time-zone data files registered .
Ole VV
5

La réponse acceptée par kael est correcte. En outre, je mentionnerai quelques choses et fournirai un diagramme sur l'obtention de la fonctionnalité java.time .

java.time intégré à Android 26+

Si vous ciblez Android 26 ou version ultérieure, vous trouverez une implémentation de JSR 310 ( classes java.time ) fournie avec Android. Pas besoin d'ajouter ThreeTenABP .

API presque identiques

Juste pour clarifier, ThreeTenABP pour Android est une adaptation de la bibliothèque ThreeTen-Backport qui apporte la plupart des fonctionnalités java.time à Java 6 et Java 7 . Ce back-port partage presque une API identique avec java.time .

Supposons que vous ciblez maintenant Android avant 26, vous utilisez donc ThreeTenABP . Plus tard, vous pourrez éventuellement abandonner la prise en charge de ces versions antérieures d'Android, pour utiliser les classes java.time fournies avec Android. Lorsque cela se produit, vous devez apporter quelques modifications à votre base de code autres que (a) les importinstructions de commutation , et (b) modifier tous les appels que vous avez effectués org.threeten.bp.DateTimeUtilspour utiliser les nouvelles méthodes de conversion qui ont été ajoutées aux anciennes classes date-heure ( Date, GregorianCalendar) .

Le processus de transition de ThreeTenABP vers java.time devrait être fluide et presque indolore.

Quand utiliser quel framework

Voici un graphique montrant les trois cadres et indiquant quand utiliser lequel dans quels scénarios.

➥ Mise à jour: Android Gradle Plugin 4.0.0+ apporte une nouvelle 4ème option, l' API désugarant pour rendre disponible un sous - ensemble de fonctionnalités java.time non intégrées à l'origine dans Android antérieur. Voir le haut de la réponse principale de kael.

Tableau de la bibliothèque java.time à utiliser avec quelle version de Java ou Android


À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, et SimpleDateFormat.

Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers les classes java.time .

Vous pouvez échanger des objets java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de java.sql.*classes. Hibernate 5 et JPA 2.2 prennent en charge java.time .

Où obtenir les classes java.time?

Basil Bourque
la source
4

Ajoutez ce qui suit dans votre fichier gradle de compilation dans Android Studio.

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

Créez la classe Application et initialisez-la comme ceci:

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