Question

Avec la sortie de pain d'épice, je l'ai expérimenté avec quelques-uns de la nouvelle API, l'un d'entre eux étant StrictMode.

Je remarque que l'un des avertissements est pour getSharedPreferences().

Ceci est l'avertissement:

StrictMode policy violation; ~duration=1949 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=23 violation=2

et il est accordée pour un appel getSharedPreferences() étant fait sur le thread d'interface utilisateur.

Accès SharedPreferences et doit-on modifier vraiment hors du thread d'interface utilisateur?

Était-ce utile?

La solution

Je suis heureux que vous êtes déjà à jouer avec elle!

Quelques choses à noter: (sous forme de balles paresseux)

  • si tel est le pire de vos problèmes, votre application est probablement dans un bon endroit. :) Les écritures sont généralement plus lents que lit, cependant, alors assurez-vous que vous utilisez au lieu de commettre SharedPreferenced $ Editor.apply () (). apply () est nouveau dans GB et async (mais toujours en sécurité, attention des transitions du cycle de vie). Vous pouvez utiliser la réflexion pour appeler certaines conditions apply () sur GB + et commit () sur Froyo ou au-dessous. Je vais faire un blogpost avec le code exemple de la façon de le faire.

En ce qui concerne le chargement, mais ...

  • une fois chargé, SharedPreferences sont singletons et processus à l'échelle mis en cache. si vous voulez l'obtenir chargé le plus tôt possible afin que vous l'avez en mémoire avant de vous en avez besoin. (En supposant qu'il est petit, comme cela devrait être si vous utilisez SharedPreferences, un simple fichier XML ...) Vous ne voulez pas lui reprocher dans le temps futur avec un utilisateur clique sur un bouton.

  • mais chaque fois que vous appelez context.getSharedPreferences (...), le fichier XML de support est stat'd pour voir si elle a changé, de sorte que vous voulez éviter ces statistiques lors d'événements de toute façon l'interface utilisateur. Une stat devrait normalement être rapide (et souvent mis en mémoire cache), mais YAFFS n'a pas beaucoup de la manière de la concurrence (et beaucoup d'appareils Android fonctionner sur YAFFS ... Droid, Nexus One, etc.) donc si vous évitez le disque , vous éviter de se retrouver derrière les autres en vol ou les opérations de disque en attente.

  • de sorte que vous aurez probablement envie de charger les SharedPreferences pendant votre onCreate () et réutiliser la même instance, en évitant la stat.

  • mais si vous n'avez pas besoin de vos préférences de toute façon pendant onCreate (), que le temps de chargement est en perte de vitesse de démarrage de votre application inutilement, il est généralement préférable d'avoir quelque chose comme un FutureTask sous-classe qui débute un nouveau thread à .set () la valeur des sous-classes de FutureTask. Ensuite, il suffit rechercher votre FutureTask est membre chaque fois que vous en avez besoin et .get (le). Je prévois d'en faire gratuitement dans les coulisses en nid d'abeille, de manière transparente. Je vais essayer de libérer quelques exemples de code qui montre les meilleures pratiques dans ce domaine.

Consultez le blog Développeurs Android pour les messages à venir sur des sujets StrictMode qui sont en la semaine prochaine (s).

Autres conseils

Accès aux préférences partagées peut prendre un certain temps parce qu'ils sont lus à partir du stockage flash. Lis-tu beaucoup? Peut-être que vous pourriez utiliser un format différent alors, par exemple une base de données SQLite.

Mais ne trouvez pas résolu tout ce que vous en utilisant StrictMode. Ou pour citer la documentation:

  

Mais ne vous sentez pas obligé de corriger tout ce Finds de StrictMode. En particulier, de nombreux cas d'accès au disque sont souvent nécessaires au cours du cycle de vie de l'activité normale. Utilisez StrictMode pour trouver des choses que vous avez fait par hasard. Les demandes de réseau sur le thread d'interface utilisateur sont presque toujours un problème, cependant.

Une subtilité au sujet de la réponse de Brad: même si vous chargez les SharedPreferences dans onCreate (), vous devriez probablement encore des valeurs sur le fil de fond parce que getString () etc bloc jusqu'à ce que la lecture de la préférence de fichier partagé dans les finitions (sur un fil de fond ):

public String getString(String key, String defValue) {
    synchronized (this) {
        awaitLoadedLocked();
        String v = (String)mMap.get(key);
        return v != null ? v : defValue;
    }
}

modifier () bloque également de la même manière, bien que apply () semble être en sécurité sur le fil de premier plan.

(BTW désolé de mettre cela ici. J'aurait mis cela comme un commentaire à la réponse de Brad, mais je vient de rejoindre et ne pas avoir assez de réputation pour le faire.)

Je sais que c'est une vieille question, mais je veux partager mon approche. J'avais de longs temps de lecture et utilisé une combinaison de préférences partagées et la classe d'application globale:

ApplicationClass:

public class ApplicationClass extends Application {

    private LocalPreference.Filter filter;

    public LocalPreference.Filter getFilter() {
       return filter;
    }

    public void setFilter(LocalPreference.Filter filter) {
       this.filter = filter;
    }
}

LocalPreference:

public class LocalPreference {

    public static void saveLocalPreferences(Activity activity, int maxDistance, int minAge,
                                            int maxAge, boolean showMale, boolean showFemale) {

        Filter filter = new Filter();
        filter.setMaxDistance(maxDistance);
        filter.setMinAge(minAge);
        filter.setMaxAge(maxAge);
        filter.setShowMale(showMale);
        filter.setShowFemale(showFemale);

        BabysitApplication babysitApplication = (BabysitApplication) activity.getApplication();
        babysitApplication.setFilter(filter);

        SecurePreferences securePreferences = new SecurePreferences(activity.getApplicationContext());
        securePreferences.edit().putInt(Preference.FILER_MAX_DISTANCE.toString(), maxDistance).apply();
        securePreferences.edit().putInt(Preference.FILER_MIN_AGE.toString(), minAge).apply();
        securePreferences.edit().putInt(Preference.FILER_MAX_AGE.toString(), maxAge).apply();
        securePreferences.edit().putBoolean(Preference.FILER_SHOW_MALE.toString(), showMale).apply();
        securePreferences.edit().putBoolean(Preference.FILER_SHOW_FEMALE.toString(), showFemale).apply();
    }

    public static Filter getLocalPreferences(Activity activity) {

        BabysitApplication babysitApplication = (BabysitApplication) activity.getApplication();
        Filter applicationFilter = babysitApplication.getFilter();

        if (applicationFilter != null) {
            return applicationFilter;
        } else {
            Filter filter = new Filter();
            SecurePreferences securePreferences = new SecurePreferences(activity.getApplicationContext());
            filter.setMaxDistance(securePreferences.getInt(Preference.FILER_MAX_DISTANCE.toString(), 20));
            filter.setMinAge(securePreferences.getInt(Preference.FILER_MIN_AGE.toString(), 15));
            filter.setMaxAge(securePreferences.getInt(Preference.FILER_MAX_AGE.toString(), 50));
            filter.setShowMale(securePreferences.getBoolean(Preference.FILER_SHOW_MALE.toString(), true));
            filter.setShowFemale(securePreferences.getBoolean(Preference.FILER_SHOW_FEMALE.toString(), true));
            babysitApplication.setFilter(filter);
            return filter;
        }
    }

    public static class Filter {
        private int maxDistance;
        private int minAge;
        private int maxAge;
        private boolean showMale;
        private boolean showFemale;

        public int getMaxDistance() {
            return maxDistance;
        }

        public void setMaxDistance(int maxDistance) {
            this.maxDistance = maxDistance;
        }

        public int getMinAge() {
            return minAge;
        }

        public void setMinAge(int minAge) {
            this.minAge = minAge;
        }

        public int getMaxAge() {
            return maxAge;
        }

        public void setMaxAge(int maxAge) {
            this.maxAge = maxAge;
        }

        public boolean isShowMale() {
            return showMale;
        }

        public void setShowMale(boolean showMale) {
            this.showMale = showMale;
        }

        public boolean isShowFemale() {
            return showFemale;
        }

        public void setShowFemale(boolean showFemale) {
            this.showFemale = showFemale;
        }
    }

}

MainActivity (activité qui s'appelle d'abord dans votre demande):

LocalPreference.getLocalPreferences(this);

Les étapes explique:

  1. L'activité principale appelle getLocalPreferences (ce) -.> Cela lire vos préférences, définir l'objet de filtre dans votre classe d'application et le renvoie
  2. Lorsque vous appelez à nouveau quelque part ailleurs la fonction getLocalPreferences () dans l'application il vérifie d'abord si elle est pas disponible dans la classe d'application qui est beaucoup plus rapide.

REMARQUE: TOUJOURS vérifier si une variable d'application large est différente de NULL, la raison -> http://www.developerphil.com/dont-store-data-in-the-application-object/

  

L'objet de l'application ne restera pas dans la mémoire pour toujours, il va se tuer. Contrairement à la croyance populaire, l'application ne sera pas redémarré à partir de zéro. Android va créer un nouvel objet et démarrez l'activité où l'utilisateur était avant de donner l'illusion que l'application n'a jamais été tué en premier lieu.

Si je n'ai pas vérifié sur null je suis d'un nullpointer d'être jeté lors de l'appel par exemple getMaxDistance () sur l'objet de filtre (si l'objet de l'application a été glissée dans la mémoire par Android)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top