L’access aux préférences partagées doit-il être effectué à partir du thread d’interface utilisateur?

Avec la sortie de Gingerbread, j’ai expérimenté certaines des nouvelles API, l’une d’entre elles étant SsortingctMode .

J’ai remarqué que l’un des avertissements concerne getSharedPreferences() .

Ceci est l’avertissement:

 SsortingctMode policy violation; ~duration=1949 ms: android.os.SsortingctMode$SsortingctModeDiskReadViolation: policy=23 violation=2 

et il est donné pour un appel getSharedPreferences() effectué sur le thread d’interface utilisateur.

L’access et les modifications de SharedPreferences doivent- SharedPreferences vraiment être faits sur le thread d’interface utilisateur?

    Je suis content que tu joues déjà avec ça!

    Quelques points à noter: (sous forme de balle paresseuse)

    • Si c’est le pire de vos problèmes, votre application est probablement bien placée. 🙂 Les écritures sont généralement plus lentes que les lectures, donc assurez-vous d’utiliser SharedPreferenced $ Editor.apply () au lieu de commit (). apply () est nouveau en Go et en asynchrone (mais toujours sûr, attention aux transitions de cycle de vie). Vous pouvez utiliser la reflection pour appeler conditionnellement apply () sur GB + et commit () sur Froyo ou ci-dessous. Je vais faire un blog avec un exemple de code sur la façon de procéder.

    En ce qui concerne le chargement, cependant …

    • Une fois chargées, les SharedPreferences sont des singletons et mises en cache à l’échelle du processus. donc vous voulez le charger le plus tôt possible pour que vous l’ayez en mémoire avant d’en avoir besoin. (en supposant que ce soit petit, comme cela devrait être le cas si vous utilisez SharedPreferences, un simple fichier XML …) Vous ne voulez pas le faire à l’avenir si certains utilisateurs cliquent sur un bouton.

    • mais à chaque fois que vous appelez context.getSharedPreferences (…), le fichier XML de sauvegarde est affiché afin de vérifier s’il a été modifié. Vous devez donc éviter ces statistiques lors des événements de l’interface utilisateur. Une stat devrait normalement être rapide (et souvent mise en cache), mais yaffs n’a pas beaucoup de concurrence (et de nombreux appareils Android fonctionnent sur yaffs … Droid, Nexus One, etc.) donc si vous évitez le disque , vous évitez de restr coincé derrière d’autres opérations de disque en attente ou en attente.

    • donc vous voudrez probablement 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 pendant le processus onCreate (), le temps de chargement ralentit inutilement le démarrage de votre application. Il est donc préférable d’avoir une sous-classe FutureTask qui lance un nouveau thread vers .set () la valeur de la sous-classe FutureTask. Ensuite, recherchez simplement le membre de votre FutureTask à chaque fois que vous en avez besoin et utilisez-le (.get ()). Je prévois de rendre cela gratuit dans les coulisses de Honeycomb, de manière transparente. Je vais essayer de publier un exemple de code qui montre les meilleures pratiques dans ce domaine.

    Consultez le blog des développeurs Android pour connaître les publications à venir sur les sujets liés à SsortingctMode au cours des prochaines semaines.

    L’access aux préférences partagées peut prendre un certain temps car elles sont lues à partir du stockage flash. Lis-tu beaucoup? Vous pourriez peut-être utiliser un format différent, par exemple une firebase database SQLite.

    Mais ne corrigez pas tout ce que vous trouvez en utilisant SsortingctMode. Ou pour citer la documentation:

    Mais ne vous sentez pas obligé de réparer tout ce que SsortingctMode trouve. En particulier, de nombreux cas d’access au disque sont souvent nécessaires pendant le cycle de vie d’une activité normale. Utilisez SsortingctMode pour trouver des choses que vous avez faites par accident. Les requêtes réseau sur le thread d’interface utilisateur posent presque toujours problème.

    Une subtilité dans la réponse de Brad: même si vous chargez les SharedPreferences dans onCreate (), vous devriez probablement toujours lire les valeurs sur le thread d’arrière-plan, car getSsortingng () bloquera jusqu’à la lecture des préférences de fichiers partagés:

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

    edit () bloque également de la même manière, même si apply () semble être sûr sur le thread de premier plan.

    (BTW désolé de mettre cela ici. J’aurais mis cela comme un commentaire à la réponse de Brad, mais je viens de rejoindre et n’ai pas assez de réputation pour le faire.)

    Je sais que c’est une vieille question mais je veux partager mon approche. J’ai eu 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.toSsortingng(), maxDistance).apply(); securePreferences.edit().putInt(Preference.FILER_MIN_AGE.toSsortingng(), minAge).apply(); securePreferences.edit().putInt(Preference.FILER_MAX_AGE.toSsortingng(), maxAge).apply(); securePreferences.edit().putBoolean(Preference.FILER_SHOW_MALE.toSsortingng(), showMale).apply(); securePreferences.edit().putBoolean(Preference.FILER_SHOW_FEMALE.toSsortingng(), 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.toSsortingng(), 20)); filter.setMinAge(securePreferences.getInt(Preference.FILER_MIN_AGE.toSsortingng(), 15)); filter.setMaxAge(securePreferences.getInt(Preference.FILER_MAX_AGE.toSsortingng(), 50)); filter.setShowMale(securePreferences.getBoolean(Preference.FILER_SHOW_MALE.toSsortingng(), true)); filter.setShowFemale(securePreferences.getBoolean(Preference.FILER_SHOW_FEMALE.toSsortingng(), 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é appelée en premier dans votre application):

     LocalPreference.getLocalPreferences(this); 

    Les étapes expliquées:

    1. Les principaux appels à l’activité getLocalPreferences (this) -> liront vos préférences, définiront l’object filtre dans votre classe d’application et le retourneront.
    2. Lorsque vous appelez à nouveau la fonction getLocalPreferences () ailleurs dans l’application, elle vérifie d’abord si elle n’est pas disponible dans la classe d’application, ce qui est beaucoup plus rapide.

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

    L’object d’application ne restra pas en mémoire pour toujours, il sera tué. Contrairement à la croyance populaire, l’application ne sera pas redémarrée à partir de zéro. Android créera un nouvel object Application et démarrera l’activité où l’utilisateur était auparavant pour donner l’illusion que l’application n’a jamais été supprimée.

    Si je ne vérifiais pas null, je permettrais à un nullpointer d’être lancé lors de l’appel, par exemple, sur getMaxDistance () sur l’object filtre (si l’object d’application était balayé de la mémoire par Android)