Pregunta

Con el lanzamiento de pan de jengibre, he estado experimentando con algunas de las nuevas API de, uno de ellos es StrictMode .

Me di cuenta de que una de las advertencias es para getSharedPreferences().

Esta es la advertencia:

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

y está siendo entregado por una llamada getSharedPreferences() están realizando en el hilo de interfaz de usuario.

En caso de acceso SharedPreferences y realmente cambios pueden hacer el hilo de interfaz de usuario?

¿Fue útil?

Solución

Me alegro de que ya se está jugando con él!

Algunas cosas para tomar nota: (en forma de bala vago)

  • si este es el peor de sus problemas, su aplicación es, probablemente, en un lugar bien. :) Las escrituras son en general más lento que lee, sin embargo, así que asegúrese de que está utilizando SharedPreferenced $ Editor.apply () en lugar de comprometerse (). aplicar () que es nuevo en GB y asíncrono (pero siempre seguro, cuidado de las transiciones del ciclo de vida). Puede utilizar la reflexión para llamar condicionalmente aplica () en GB + y commit () en Froyo o por debajo. Voy a estar haciendo una entrada de blog con el código de ejemplo de cómo hacer esto.

En cuanto a la carga, aunque ...

  • Una vez cargado, SharedPreferences son únicos y en caché proceso de ancho. por lo que desea conseguir cargado tan pronto como sea posible para que lo tienes en la memoria antes de que lo necesite. (Asumiendo que es pequeña, como debe ser si usted está utilizando SharedPreferences, un simple archivo XML ...) Usted no quiere poner ninguna pega en el momento en el futuro algún usuario hace clic en un botón.

  • pero cada vez que se llama a context.getSharedPreferences (...), el archivo XML de soporte está stat'd para ver si se ha cambiado, por lo que querrá evitar esas estadísticas durante los eventos de interfaz de usuario de todos modos. Una estadística que normalmente debería ser rápido (y, a menudo en caché), pero yaffs no tiene mucho en el camino de la concurrencia (y una gran cantidad de dispositivos Android se ejecutan en yaffs ... Droid, Nexus One, etc.) por lo que si usted evita disco , que evitar quedarse atascado detrás de otros en vuelo o en vías de operaciones de disco.

  • por lo que probablemente quiere cargar los SharedPreferences durante su onCreate () y volver a utilizar la misma instancia, evitando la estadística.

  • pero si usted no necesita sus preferencias de todos modos durante onCreate (), que el tiempo de carga está estancando la puesta en marcha de su aplicación sin necesidad, por lo que es generalmente mejor tener algo así como un FutureTask subclase que se inicia un nuevo hilo a .SET () valor de las subclases FutureTask. A continuación, sólo las operaciones de búsqueda de su FutureTask 's miembro y siempre que lo .get () lo necesite. Tengo la intención de hacer esta conexión entre bastidores en nido de abeja, de forma transparente. Voy a tratar de liberar un código de ejemplo, que muestra las mejores prácticas en este ámbito.

Comprobar el blog de desarrolladores de Android para los próximos mensajes sobre temas StrictMode-relacionadas en la próxima semana (s).

Otros consejos

Acceso a las preferencias compartidas puede tomar bastante tiempo, ya que se leen de almacenamiento flash. ¿Lees mucho? Tal vez usted podría utilizar un formato diferente, entonces, por ejemplo, una base de datos SQLite.

Sin embargo, no lo arregles todo lo que encuentre utilizando StrictMode. O citar la documentación:

Pero no se siente obligado a arreglar todo lo que StrictMode hallazgos. En particular, muchos casos de acceso a disco son a menudo necesarios durante el ciclo de vida de la actividad normal. Uso StrictMode para encontrar cosas que hizo por accidente. las solicitudes de red en el hilo de interfaz de usuario son casi siempre un problema, sin embargo.

Una sutileza sobre la respuesta de Brad: incluso si se cargan los SharedPreferences en onCreate (), debe probablemente todavía leer valores en el subproceso en segundo plano, porque getString (), etc. bloque hasta que la lectura de la preferencia de archivos compartidos en los acabados (en un subproceso en segundo plano ):

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

editar () también bloquea la misma manera, aunque apply () parece ser seguro en el subproceso de primer plano.

(Por cierto siento a poner esto aquí. Me habría puesto esto como un comentario a la respuesta de Brad, pero me acaba de unirse y no tienen la reputación suficiente para hacerlo.)

Sé que esto es una vieja pregunta, pero quiero compartir mi enfoque. Había largos tiempos de lectura y se utiliza una combinación de preferencias compartidas y la clase de aplicación mundial:

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 (actividad que consiga llamar por primera vez en su aplicación):

LocalPreference.getLocalPreferences(this);

Pasos explicó:

  1. llama La actividad principal getLocalPreferences (este) -.> Esto leerá sus preferencias, establecer el objeto de filtro en su clase de aplicación y lo devuelve
  2. Cuando se llama a los getLocalPreferences () de nuevo en otro lugar en la aplicación comprueba en primer lugar si no es disponible en la clase de aplicación que es mucho más rápido.

NOTA: Compruebe siempre que una amplia variable de aplicación es diferente de NULL, la razón -> http://www.developerphil.com/dont-store-data-in-the-application-object/

El objeto de la aplicación no se quedará en la memoria para siempre, va a ser asesinado. Contrariamente a la creencia popular, la aplicación no se reinicia desde cero. Android va a crear un nuevo objeto de aplicación e iniciar la actividad en la que el usuario estaba antes para dar la ilusión de que la aplicación nunca murió en el primer lugar.

Si no me registro en nulo que permitiría a un NullPointer a ser lanzado al llamar por ejemplo getMaxDistance () en el objeto de filtro (si el objeto de la aplicación se limpió de la memoria por Android)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top