Frage

Mit der Veröffentlichung von Lebkuchen, ich habe mit einigen der neuen API experimentiert, ist einer von ihnen StrictMode .

Ich habe bemerkt, dass eine der Warnungen für getSharedPreferences() ist.

Dies ist die Warnung:

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

und es ist für einen getSharedPreferences() Anruf gegeben wird auf dem UI-Thread gemacht werden.

Should SharedPreferences Zugriff und Änderungen wirklich aus dem UI-Thread gemacht werden?

War es hilfreich?

Lösung

Ich bin froh, dass du schon mit ihm spielen!

Einige Dinge zu beachten: (in faul Kugel-Form)

  • , wenn dies die schlimmste Ihrer Probleme ist, Ihre Anwendung ist wahrscheinlich eine gute Lage. :) Writes sind in der Regel langsamer als liest, obwohl, so sicher sein, du bist SharedPreferenced $ Editor.apply () anstelle von commit () verwenden. () Gelten ist neu in GB und Asynchron (aber immer sicher, vorsichtig von Lifecycle-Übergängen). Sie können Reflektion verwenden, um bedingt (Anruf gilt) auf GB + und commit () auf Froyo oder unten. Ich werde einen Blogpost mit Beispielcode, wie dies zu tun tun.

In Bezug auf Belastung, obwohl ...

  • einmal geladen, SharedPreferences sind Singletons und zwischengespeichert Prozess weit. so Sie erhalten möchten geladen es so früh wie möglich, so dass Sie es in Erinnerung haben, bevor Sie es brauchen. (Es ist klein angenommen, wie es sein sollte, wenn Sie verwenden SharedPreferences, eine einfache XML-Datei ...) Sie wollen nicht, es in der Zukunft Zeit bemängeln einige Benutzer auf eine Schaltfläche klickt.

  • aber wenn Sie context.getSharedPreferences nennen (...), die Unterstützung von XML-Datei wird stat'd zu sehen, ob es sich geändert hat, so dass Sie auf jeden Fall diese Statistiken während UI Ereignisse vermeiden wollen werden. Ein Stat sollte in der Regel schnell (und oft zwischengespeichert), aber yaffs nicht viel in der Art und Weise der Parallelität (und vielen Android-Geräte läuft auf yaffs ... Droid, Nexus One, etc.) so, wenn Sie Datenträger vermeiden vermeiden Sie hinter anderen im Flug oder anhängigen Plattenoperationen stecken zu bleiben.

  • so werden Sie wahrscheinlich wollen die SharedPreferences während Ihres onCreate () und Wiederverwendung der gleichen Instanz laden, den Stat zu vermeiden.

  • aber wenn Sie Ihre Einstellungen nicht ohnehin während onCreate müssen (), die Ladezeit Ihrer App Inbetriebnahme unnötig stockt, so besser ist es im Allgemeinen etwas zu haben, wie ein FutureTask Unterklasse, dass Kicks off ein neuer Thread () das FutureTask Subklassen der Wert .set. Dann einfach Nachschlag Ihre FutureTask 's Mitglied, wenn Sie es und .get () es brauchen. Ich plane, diese transparent hinter den Kulissen in Honeycomb frei zu machen. Ich werde versuchen, einige Beispiel-Code zur Freigabe der zeigt Best Practices in diesem Bereich.

Überprüfen Sie die Android Developers Blog zu den kommenden Beiträge über StrictMode-verwandten Themen in der kommenden Woche (n).

Andere Tipps

kann die gemeinsame Vorlieben Zugriff auf einige Zeit dauern, weil sie aus dem Flash-Speicher gelesen werden. Liest du viel? Vielleicht könnte man dann ein anderes Format verwenden, z.B. eine SQLite-Datenbank.

Aber nicht fix alles, was Sie mit StrictMode finden. Oder in der Dokumentation zu zitieren:

Aber nicht das Gefühl, zu reparieren alles dazu gezwungen, dass StrictMode Funde. Insbesondere sind viele Fälle von Plattenzugriff oft notwendig, während der normalen Aktivität Lebenszyklus. Verwenden StrictMode zu finden Dinge, die Sie zufällig tat. Netzwerkanforderungen auf dem UI-Thread sind fast immer ein Problem, wenn.

Eine Subtilität über Brad Antwort: Auch wenn Sie die SharedPreferences in onCreate () laden, sollten Sie wahrscheinlich immer noch Werte auf dem Hintergrund-Thread lesen, weil getString () usw. Block, bis die freigegebene Datei bevorzugt in den Ausführungen zu lesen (auf einem Hintergrund-Thread ):

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

Bearbeiten () blockiert auch in der gleichen Art und Weise, obwohl apply () erscheint auf dem Vordergrundthread, sicher zu sein.

(BTW leider hier, um diese nach unten zu setzen. Ich habe diese Antwort als Kommentar zu Brad hätte, aber ich gerade beigetreten und habe nicht genug Ruf, dies zu tun.)

Ich weiß, das ist eine alte Frage, aber ich will meinen Ansatz teilen. Ich hatte lange Zeit zu lesen und verwenden eine Kombination aus gemeinsamen Vorlieben und die globale Anwendungsklasse:

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 (Aktivität, die zuerst in der Anwendung aufgerufen werden):

LocalPreference.getLocalPreferences(this);

Schritte erklärt:

  1. Die Haupttätigkeit nennt getLocalPreferences (this). -> dies Ihre Einstellungen gelesen wird, setzen Sie das Filterobjekt in Ihrer Anwendungsklasse und gibt es
  2. Wenn Sie rufen die getLocalPreferences () Funktion wieder irgendwo anders in der Anwendung zunächst überprüft, ob es in der Anwendungsklasse nicht verfügbar ist, die viel schneller ist.

Hinweis: Prüfen Sie stets, ob eine Anwendung weite Variable von NULL verschieden ist, Grund -> http://www.developerphil.com/dont-store-data-in-the-application-object/

Das Anwendungsobjekt wird nicht für immer in Erinnerung bleiben, wird es getötet. Entgegen der landläufigen Meinung, wird die App nicht von Grund auf neu gestartet werden. Android wird ein neues Anwendungsobjekt erstellen und die Aktivität beginnen, wo der Benutzer war, bevor die Illusion zu geben, dass die Anwendung nie an erster Stelle getötet wurde.

Wenn ich nicht auf null überprüfen habe ich erlauben würde, eine Nullpointer geworfen werden, wenn zum Beispiel getMaxDistance () auf dem Filterobjekt aufrufen (wenn das Anwendungsobjekt aus dem Speicher von Android geklaut wurde)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top