Android: las preferencias compartidas establecidas en un AsyncTask onPostExecute () no siempre se establecen?

Tengo un código que funciona el 98% del tiempo y el 100% durante mis propias pruebas, así que realmente no puedo reproducir el problema aparte de tener dispositivos de usuario que experimenten este problema.

Lo que hago en onPostExecute () se establece un parámetro como este:

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( AddProblemActivity.this); prefs.edit().putString("recent_problem_id", result ).commit(); 

Y luego vaya a la siguiente actividad:

  Intent myIntent = new Intent(AddProblemActivity.this, ProblemActivity.class); AddProblemActivity.this.startActivity(myIntent); 

Y luego tratar de obtener ese parámetro allí como este:

 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( ProblemActivity.this); // display a loading message before problem loads. String recent_problem_id = prefs.getString( "recent_problem_id" , null ); if ( recent_problem_id == null ) { // Sometimes it is null! } 

¿Alguien sabe por qué sucede esto?

¡Gracias!

Si está intentando pasar los datos a una nueva actividad, ¿por qué no ponerla como una cadena extra en la intención? A continuación, obtenga esa cadena de la intención en la nueva actividad. Si todavía necesita almacenarlo, puede hacerlo en la nueva actividad onCreate () después de que lo tire de la intención.

 Intent myIntent = new Intent(AddProblemActivity.this, ProblemActivity.class); //Add results here myIntent.putExtra("RecentProblemId", result); AddProblemActivity.this.startActivity(myIntent); 

Luego, en la clase de su nueva Actividad, haga lo siguiente:

 String recentProblemId = getIntent().getStringExtra("RecentProblemId"); 

Ahora, si todavía necesita esta información almacenada, haga lo siguiente:

 if(recentProblemId != null){ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( ProblemActivity.this); prefs.putString("recent_problem_id",recentProblemId).commit(); } 

Sé que esto no responde exactamente a su pregunta en cuanto a porqué la secuencia no está siendo confiada siempre a las preferencias en onPostExecute (). Sin embargo, la mejor práctica para pasar información entre actividades es a través de Intents y extras.

Mi suposición de por qué no siempre funciona para algunos usuarios, es que sus dispositivos no se terminan de escribir los datos en el archivo de preferencias compartidas antes de que se inicie la nueva actividad e intenta leer de ese mismo archivo. Espero que esto ayude.

Primero de todo, vea la respuesta de Raghav Sood.
Hay un momento delicado. Puede empezar a ejecutar su AsyncTask que girar el dispositivo. La actividad será recreada y en PostExecute tendrá un contexto incorrecto para que sus preferencias no se guarden.
Si es verdad, debe usar onRetainNonConfigurationInstance () para guardar la instancia de la tarea apropiada.

No estoy seguro acerca de esto, pero creo que el problema puede ser debido a la diferencia en el contexto que está pasando. Está utilizando el Contexto de AddProblemActivity primero y luego el Contexto de ProblemActivity . Intente usar una preferencia de conjunto, como un nombre de archivo:

 SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE); 

Tenga en cuenta que getSharedPreferences () es un método de Contexto, por lo que necesitará tener una referencia a una Actividad o quizás Contexto de Aplicación en su AsyncTask para poder usarlo.

Parece que su código está bien y no hay razón por la que no debería funcionar, la única razón será algún defecto que probablemente esté relacionado con el dispositivo. Mis pensamientos son desde el Prefs compartido se guardan en el almacenamiento local algo puede ir mal en el proceso.

Como se aconseja en los comentarios, será imprescindible agregar un registro de tipo de dispositivo, te recomendaría que utilices "ACRA" – http://code.google.com/p/acra/ que te puede proporcionar informes detallados con un mínimo esfuerzo (Preste la atención que usted puede enviar un informe no necceserily solamente en choque de la aplicación).

Echa un vistazo a este hilo, muestra un problema que tal vez estás experimentando también: SharedPreferences no guardar / cargar en PreferenceActivity . Si es el caso, una solución será gestionar el almacenamiento de estos datos persistentes manualmente en el almacenamiento local o utilizar una solución de base de datos. Buena suerte 🙂

Creo que el problema se debe a que la configuración de preferencia compartida no se escribe en su sistema de archivos aún cuando intenta acceder a él desde su segunda actividad. Usted menciona que escribe el ajuste del método onPostExecute (de un AsyncTask tal vez?). Al iniciar un AsyncTask no hay garantía de que se inicie inmediatamente. La única garantía que hay, es que se iniciará en un hilo de fondo. La plataforma puede y decidirá cuándo ejecutar realmente el hilo de fondo, dependiendo de la carga del sistema, los bloques del sistema de archivos o así. Podría muy bien ser para que su AsyncTask no se ha iniciado todavía cuando cambia a la segunda actividad (y, por tanto, el método onPostExecute no se ha llamado aún).

Guardar las preferencias compartidas es difícil cuando escriben en el sistema de archivos. Usted podría terminar bloqueando el hilo principal si no tiene cuidado. El objeto SharedPreferences.Editor tiene un método de apply que actualizará inmediatamente el caché en memoria de sus preferencias compartidas (haciendo que los cambios estén disponibles a la vez) y la patada de un subproceso de fondo para guardar el valor real en el sistema de archivos. Así que mi consejo sería que si usted tiene la posibilidad, usted debe tratar de llamar el método de apply (desde el hilo principal) en lugar del método commit de (lo que asumo) un AsyncTask . El método apply requiere API de nivel 9 o superior.

Para su referencia: http://developer.android.com/reference/android/content/SharedPreferences.Editor.html

Editar:

El método commit devolverá un valor booleano dependiendo del resultado de la operación de escritura. ¿Podría (debería?) Comprobar que el valor de retorno para poder al menos poder tomar medidas correctas en caso de falla (como mostrar un "no se pudo guardar su configuración, por favor intente de nuevo" tostadas o algo).

Saludos, –dbm

Podría estar equivocado. Pero creo que un amigo mío tuvo un problema similar una vez. Yo estaba atascado en este problema durante horas. Los resultados para más como el 30% del tiempo no funcionaría. Creo que el onPostExecute () se ejecuta en un hilo separado cuando el Intent se instancia y se llama a la actividad. Esto se debe a que un AsyncTask se implementa en un subproceso independiente. Dependiendo del dispositivo, esto se llamaría más probable entonces no. Nuestra tableta que rara vez sucedió, en el teléfono inteligente que se producen más comúnmente.

Puede probar esto depurando la aplicación y mirando el hilo de AsyncThread y ver cuándo se realiza la llamada.

Sí, es mejor enviar la variable a través de la putExtra ().

Espero que esto ayude a entender por qué ocurrió esto.

La acción de commit de SharePreferences es synchroneos así que no creo que el hecho de que estés iniciando la nueva intención debería afectarla, solo que la acción commit no es a prueba de fallos, puede fallar.

http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#commit ()

Devuelve true si los nuevos valores se escribieron correctamente en almacenamiento persistente.

Tal vez debería comprobar que el valor de retorno para asegurarse de que se las arregló para guardar el resultado.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.