2011-09-19 14 views
8

Estoy trabajando en mi primera aplicación de Android. Tiene un modelo que persiste en una base de datos a medida que el usuario realiza actualizaciones.onSaveInstanceState/onPause: espere hasta que el estado se guarde completamente antes de permitir que se mate el proceso

Cuando se llama a onSaveInsanceState, deseo guardar una identificación que se puede usar para cargar el documento en el que el usuario estaba trabajando desde la base de datos. Pero esto solo puede suceder una vez que el documento ha golpeado completamente la base de datos. En algunos casos, persistir un documento complejo puede llevar varios segundos (espero que esto se acelere una vez que elimine todo el cierre de sesión detallado, y en el uso real, el usuario creará un documento complejo por etapas, cada uno de los cuales se mantendrá en la base de datos, por lo que no es muy probable que todos los documentos complejos se guarden de una sola vez).

Ahora, la regla # 1 de enhebrar en Android es "no bloquear el hilo de la interfaz de usuario", por lo que, por supuesto, las interacciones DB ocurren en un hilo separado. Pero mi comprensión del ciclo de vida de Android es que en muchos casos se llama a OnSaveInstanceState porque el sistema Android quiere matar el proceso. Eso sugiere que no puedo permitir que este método regrese hasta que el hilo DB termine de guardar el documento (y de hecho con mi diseño actual, realmente no sé cuál es el número de identificación del documento hasta que se haya guardado en el DB, así que ni siquiera puedo poner eso en el paquete de estado guardado).

¿Es apropiado en estas circunstancias bloquear el subproceso de interfaz de usuario esperando a que se complete la tarea? Cuando se llama al onSaveInstanceState porque el proceso está siendo cancelado, la aplicación ya no está visible en el primer plano, por lo que no hay interfaz que no responda.

Pero también se llama a onSaveInstanceState cuando la instancia de actividad se está destruyendo mediante una actualización de configuración, que ocurre cuando cambia la orientación de la pantalla. Es muy desafortunado que al girar la pantalla de lado no se haga nada durante varios segundos. En este caso, el proceso (y, por lo tanto, el espacio de memoria) aún está presente, por lo que no es necesario que el documento llegue a la base de datos, solo puedo almacenar una referencia en el paquete en lugar de su identificación. Pero no conozco una forma de diferenciar entre estos dos casos.

¿Existe una práctica aceptada para estas situaciones? ¿Debo simplemente bloquear el hilo para estar seguro? ¿Puedo usar primitivas de hilo Java normales para bloquear y esperar? ¿Existe algo que pueda hacer que no bloquee el hilo pero asegura que la tarea de persistencia se finalizará antes de que Android cierre el proceso?

Todo esto también se aplica a , ya que no es necesario llamar a onSaveInstanceState.

Respuesta

0

Debería probar AsyncTask, que bloqueará su interfaz de usuario pero no mostrará la pantalla en blanco, cargará los elementos xml necesarios y luego recibirá la llamada de la tarea Async, en la tarea asincrónica guardará su documento en la base de datos.

Siga este enlace: AyncTask Exmaple

+0

Pensé que el objetivo de 'AsyncTask' era que * no * bloquea el hilo de UI? ¿No es ese el objetivo de usarlo para hacer operaciones duraderas? – Ben

+0

Si tiene problemas con los cambios de la configuración, no se preocupe, simplemente escriba los cambios de configuración en su archivo de mainfest en esta etiqueta de actividad, de modo que nunca invocará aSaveInstanceState() cuando se cambie la orientación. No obligará a la actividad a reiniciarse –

+0

Eso es práctico (pero tiene sus propios problemas), pero es completamente irrelevante para la pregunta, que es cómo me aseguro de que los datos persistentes que realmente se guardan cuando la aplicación se elimine si el guardado se realiza mediante un fondo hilo. – Ben

2

Usted no tiene que ver con el ahorro persistente en onSaveInstanceState, puede prácticamente sólo guardar el estado de la instancia en el Bundle para que la instancia puede ser rápidamente reanudó en onRestoreInstanceState.

La Documentación indica que debe escribir datos persistentes cruciales (como ediciones de usuario) en el almacenamiento en , pero también indica que debe ser rápido para que la siguiente actividad pueda comenzar a hacer lo que quiera hacer.

Creo que mi recomendación aquí sería simplemente guardar el texto del documento y todo lo que está en el paquete en onSaveInstanceState y restaurarlo en onRestoreInstanceState. Use para guardar una "copia de seguridad" en algún lugar rápido (¿quizás un archivo temporal?) Que luego puede restaurarse en onResume si no se ha guardado en la base de datos. Y use onStop (que se llama cuando la actividad ya está en segundo plano) para guardar realmente los datos en la base de datos.

Tenga en cuenta que la actividad puede ser cancelada después de que se haya llamado (nunca antes, a menos que el sistema tenga muy pocos recursos ...), es por eso que guardaría una copia de seguridad rápida antes de intentar comprometerla en la base de datos .

Editar - extra basado en los comentarios

Para asegurarse de que el subproceso de fondo que está haciendo el proceso de ahorro se hace ahorrar antes de la aplicación puede ser matado por el sistema, creo que está bien para bloquear y esperar para que se complete el hilo de guardado antes de regresar del , pero recomiendo usar android:configChanges="orientation" para evitar el reinicio de la actividad (y la llamada a) cuando cambie la orientación.

+0

De hecho, confío todo a la base de datos tan pronto como se escribe. No lo hago en 'onSaveInstanceState'. El problema es que la última operación de salvar desencadenada * aún puede estar en curso * cuando se invoca 'onSaveInstanceState'. Necesito saber cómo esperar para decirle al sistema Android "está bien matarme ahora" hasta que la información persistente sea realmente segura. Si el sistema tiene tan pocos recursos que arbitrariamente mata mi proceso de todos modos, está bien que se pierdan ediciones sin columnas, pero no quiero que el proceso muera a mitad de una operación de DB bajo condiciones normales de operación. – Ben

+0

En ese caso, puede omitir 'onSaveInstanceState' utilizando android: configChanges =" orientation "en su archivo de manifiesto como lo sugiere mak_just4anything. Solo asegúrate de que el guardado esté hecho en 'onPause' /' onStop'. Más información aquí: http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange – Zharf

+0

Obviamente no estoy haciendo que mi pregunta sea comprendida. Digamos que mi 'onPause' llama' tellBackgroundThreadToSaveStateToDb'. Bueno. Hecho. Ahora, ¿cómo me aseguro de que el hilo de fondo todavía no está procesando esa solicitud cuando Android quiere matar mi proceso? – Ben

Cuestiones relacionadas