Usar SharedPreferences en modo multiproceso
He definido una instancia de SharedPreferences
que se utiliza en el modo multi-proceso.
public class Prefs { private static SharedPreferences prefs; private static SharedPreferences.Editor editor; private static void init(Context context) { prefs = context.getSharedPreferences("alaki", Context.MODE_MULTI_PROCESS); editor = prefs.edit(); } // static methods to set and get preferences }
Ahora estoy usando esta clase en un servicio con proceso separado y también en mi proceso de aplicación principal de manera estática.
Todo va bien, pero a veces todos los datos almacenados en la instancia SharedPreferences eliminado!
¿Como puedó resolver esté problema?
- Preferencias independientes para cada vista en una aplicación para Android
- Sharedpreference con la pantalla de bienvenida
- BackupManager no llama al servicio de transporte de copia de seguridad
- Almacenamiento de una matriz String en SharedPreferences
- Botón Inicio de la barra de acciones no funcional con PreferredScreen anidado
Edit: Finalmente he resuelto mi problema usando por IPC.
- Unidad de Google para realizar copias de seguridad y restaurar la base de datos y las preferencias compartidas de la aplicación de Android
- NullPointerException en SharedPreferences Android
- SharedPrefs se restablece después de configurar la configuración regional de la aplicación de Android
- Cerrar sesión cerrar SharedPreferences
- Preferencia y comprobación de la casilla de verificación si está activada o desactivada
- Cómo resolver un error: getSharedPreferences (String, int) no está definido para el tipo nuevo View.OnClickListener () {}
- No se puede acceder a las preferencias creadas por PreferenceActivity
- ¿La aplicación de actualización borra las preferencias compartidas o elimina las alarmas establecidas por la aplicación?
Actualmente no hay forma de acceder de forma segura a SharedPreferences
en múltiples procesos, como se describe en su documentación .
Nota: actualmente esta clase no admite el uso a través de múltiples procesos. Esto se agregará más tarde.
Después de probar mucho con MODE_MULTI_PROCESS
, tengo tres ensayos para compartir:
1- Inicializar las SharedPreferences
una vez en cada proceso y usarlo varias veces.
El problema: Los valores no se reflejan en cada proceso como se esperaba. Así que cada proceso tiene su propio valor de SharedPreferences.
2- Inicializar las SharedPreferences
en cada put o get.
Esto realmente funciona y el valor ahora es intercambiable entre procesos.
El problema: a veces, después de acceder agresivamente al sharedpref, el archivo de preferencias compartidas se eliminó con todo su contenido, como se describe en este número , y recibo esta advertencia en el registro:
W/FileUtils﹕ Failed to chmod(/data/data/com.hegazy.multiprocesssharedpref/shared_prefs/myprefs.xml): android.system.ErrnoException: chmod failed: ENOENT (No such file or directory)
Puede averiguar por qué sucede esto en el problema.
3- Utilice la sincronización para bloquear los métodos que ponen y obtienen valores en SharedPreferences
.
Esto es completamente incorrecto; La sincronización no funciona en todos los procesos. SharedPreferences
utiliza en realidad la sincronización en su implementación, pero sólo garantiza la seguridad de los subprocesos, no la seguridad del proceso. Esto se describe muy bien aquí .
SharedPreferences no es un proceso seguro. Eso es probablemente por qué la documentación de SharedPreferences dice
Nota: actualmente esta clase no admite el uso a través de múltiples procesos. Esto se agregará más tarde.
He trabajado en torno a esto mediante la combinación de:
- Proporcionar a cada proceso un acceso mutuamente exclusivo al archivo
SharedPreferences
(por ejemplo, mediante un mecanismo de bloqueo basado en socket ) -
SharedPreferences
lasSharedPreferences
con el indicadorMODE_MULTI_PROCESS
cada vez que lo desee para omitir la memoria caché en memoria
Esto parece funcionar bien, pero no ha sido probado a fondo en el mundo real, así que no sé si es perfectamente confiable.
Puedes ver un ejemplo de trabajo que escribí aquí .
Advertencia : Parece que MODE_MULTI_PROCESS
ha quedado obsoleto en Android M. Podría dejar de funcionar en el futuro.
Usando el método commit()
almacenar los cambios en el almacenamiento persistente, por lo que es lento y haría que el conflicto a través de múltiples llamadas de otros procesos.
Sin embargo hay una alternativa a este método, debe llamar al método apply()
, este método almacena los cambios en la memoria y luego en el almacenamiento de disco de forma asíncrona, por lo que es más fiable.
Recuerda que el uso de objetos de contexto como campo estático, tiene el riesgo de fuga de contexto porque no declarar el objeto en la clase de aplicación
public class CustomApplication extends Application{ private Prefs prefs; public void onCreate(){ prefs = new Prefs(this); } public Prefs getPrefs(){ return prefs; } }
Desde cualquier contexto se pueden obtener las preferencias
((MyApplication)context.getApplicationContext()).getPrefs();
Utilice un proveedor de contenido que utilice SharedPreferences. Ejemplo vea aquí: https://github.com/hamsterksu/MultiprocessPreferences
Si dos procesos escriben datos en SharedPreferences, es posible que todas las SharedPreferences se restablezcan a valores predeterminados.
También puede intentar llamar a clear()
en el editor antes de almacenar val
SharedPreferences.Editor sp = settings.edit(); sp.clear(); sp.putString("Name", "YourName"); sp.commit();
- Consultar proveedor de contenido de Android desde la línea de comandos (shell de anuncios)
- No se puede crear una sala de chat multiusuario (MUC) con la biblioteca aSmack para Android: "packet.DefaultPacketExtension no se puede convertir en paquete.MUCUser"