57 votes

Android Java - Joda La date est lente

Utiliser Joda 1.6.2 avec Android

Le code suivant se bloque pendant environ 15 secondes.

 DateTime dt = new DateTime();
 

A l'origine posté cet article Android Java - Joda La date est lente dans Eclipse / Emulator -

Juste essayé à nouveau et ce n'est toujours pas mieux. Est-ce que quelqu'un d'autre a ce problème ou sait comment le résoudre?

64voto

plowman Points 5106

J'ai aussi rencontré ce problème. Jon Skeet les soupçons étaient corrects, le problème est que les fuseaux horaires sont chargés vraiment inefficace, l'ouverture d'un fichier jar, puis la lecture du manifeste pour essayer d'obtenir cette information.

Toutefois, simplement en appelant DateTimeZone.setProvider([custom provider instance ...]) n'est pas suffisante, car, pour des raisons qui ne font pas de sens pour moi, DateTimeZone a un initialiseur statique où elle appelle getDefaultProvider().

Pour être complètement sûr, vous pouvez remplacer cette valeur par défaut en définissant cette propriété du système avant de vous jamais demandé quoi que ce soit dans le joda.

Dans votre activité, par exemple, ajouter ceci:

@Override
public void onCreate(Bundle savedInstanceState) {
    System.setProperty("org.joda.time.DateTimeZone.Provider", 
    "com.your.package.FastDateTimeZoneProvider");
}

Ensuite, tout ce que vous avez à faire est de définir FastDateTimeZoneProvider. J'ai écrit ce qui suit:

package com.your.package;

public class FastDateTimeZoneProvider implements Provider {
    public static final Set<String> AVAILABLE_IDS = new HashSet<String>();

    static {
        AVAILABLE_IDS.addAll(Arrays.asList(TimeZone.getAvailableIDs()));
    }

    public DateTimeZone getZone(String id) {
        if (id == null) {
            return DateTimeZone.UTC;
        }

        TimeZone tz = TimeZone.getTimeZone(id);
        if (tz == null) {
            return DateTimeZone.UTC;
        }

        int rawOffset = tz.getRawOffset();

            //sub-optimal. could be improved to only create a new Date every few minutes
        if (tz.inDaylightTime(new Date())) {
            rawOffset += tz.getDSTSavings();
        }

        return DateTimeZone.forOffsetMillis(rawOffset);
    }

    public Set getAvailableIDs() {
        return AVAILABLE_IDS;
    }
}

J'ai testé cela et il semble fonctionner sur Android SDK 2.1+ avec joda de la version 1.6.2. Il peut bien sûr être optimisé, mais tout de profilage de mon application (mogwee), cette diminution de la DateTimeZone initialiser le temps de ~500ms à ~18ms.

Si vous utilisez proguard construire votre application, vous devez ajouter cette ligne à proguard.cfg car Joda attend le nom de la classe à être exactement comme vous le précisez:

-keep class com.your.package.FastDateTimeZoneProvider

23voto

Jon Skeet Points 692016

Je vous soupçonne que c'est parce que c'est d'avoir à construire l'ISO chronologie pour le fuseau horaire par défaut, ce qui implique sans doute la lecture de toutes les informations de fuseau horaire.

Vous pouvez vérifier cela en appelant ISOChronology.getInstance() premier temps, et ensuite, le temps d'un appel ultérieur à l' new DateTime(). Je soupçonne ça va être rapide.

Savez-vous à quel moment les zones vont être pertinent dans votre application? Vous pouvez trouver que vous pouvez rendre la chose beaucoup plus rapide par la reconstruction de Joda Temps avec une très grande réduction de temps de la zone de la base de données. Sinon, appelez - DateTimeZone.setProvider() avec votre propre mise en œuvre de l' Provider ce qui ne veut pas faire autant de travail.

Il vaut la peine de vérifier si c'est effectivement le problème en premier lieu, bien sûr :) Vous pouvez aussi voulez essayer explicitement passant dans le fuseau horaire UTC, qui n'ont pas besoin de lire dans le fuseau horaire de base de données... bien que vous ne savez jamais quand vous aurez accidentellement déclencher un appel qui ne nécessitent le fuseau horaire par défaut, à quel point vous aurez à assumer les coûts.

10voto

Tyler Collier Points 1917

Je n'ai besoin que de l'heure UTC dans ma candidature. Donc, suivant les conseils de Unchek, j'ai utilisé

 System.setProperty("org.joda.time.DateTimeZone.Provider", "org.joda.time.tz.UTCProvider");
 

org.joda.time.tz.UTCProvider est réellement utilisé par JodaTime en tant que sauvegarde secondaire, alors je me suis demandé pourquoi ne pas l'utiliser pour un usage principal? Jusqu'ici tout va bien. Ca charge vite.

8voto

Ricardo Points 1188

Le haut de réponse fournis par le laboureur n'est pas fiable si vous devez exacte, fuseau horaire calculs pour vos dates. Voici un exemple de problème qui peut se produire:

Supposons que votre DateTime objet est, pour le 4:00 du matin, une heure après l'heure d'été ont commencé le jour même. Lorsque Joda vérifie l' FastDateTimeZoneProvider fournisseur avant 3:00 du matin (c'est à dire, avant de l'heure d'été), il sera d'obtenir un DateTimeZone objet avec le mauvais offset parce que l' tz.inDaylightTime(new Date()) vérifier retournera false.

Ma solution a été d'adopter la a récemment publié joda-time-android bibliothèque. Il utilise la base de Joda, mais fait en sorte de charger un fuseau horaire, au besoin seulement de la crue du dossier. La configuration est facile avec gradle. Dans votre projet, étendre l' Application de la classe et d'ajouter ce qui suit sur son onCreate():

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        ResourceZoneInfoProvider.init(this);
    }
}

L'auteur a écrit un billet de blog à ce sujet l'année dernière.

3voto

Steven Elliott Points 1599

Je peux confirmer ce problème avec les versions 1, 1.5 et 1.62 de joda. Date4J fonctionne bien pour moi comme alternative.

http://www.date4j.net/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X