2011-11-30 13 views
6

estoy tratando de seguir las mejores prácticas de Android, por lo que en el modo de depuración enciendo la siguiente información en:¿Es apropiado el acceso de archivos SQL o generales en el hilo de la interfaz de usuario principal de Android?

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all thread violations 
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all virtual machine violations 

Android ahora me grita cuando intento utilizar cualquier tipo de acceso a archivos o SQL en el principal (UI) hilo. Pero veo tantas recomendaciones para usar acceso a archivos y/o SQL en el hilo principal. Por ejemplo, la actividad principal debe cargar los valores por defecto de preferencia dentro onCreate() en caso de que no se han fijado todavía:

PreferenceManager.setDefaultValues(context, resId, readAgain); 

Vaya --- que da como resultado un acceso a archivos en la primera ejecución de la aplicación, ya que se llama onCreate() en el hilo de la interfaz de usuario La única forma de evitarlo que puedo ver es comenzar un hilo separado --- que introduce una condición de carrera con otro código de UI que podría leer las preferencias y esperar que los valores predeterminados ya estén establecidos.

Piense también en servicios como el DownloadManager. (En realidad, es tan defectuoso que es inútil en la vida real, pero imaginemos que funciona por un segundo.) Si pone en cola una descarga, obtiene un evento (en el hilo principal) indicándole que la descarga ha finalizado. Para obtener realmente información sobre esa descarga (solo le da una ID de descarga), debe consultar el DownloadManager --- que implica un cursor, que le da un error si tiene activada una política estricta.

¿Cuál es la historia --- ¿está bien acceder a los cursores en el hilo principal? ¿O es algo malo, y la mitad del equipo de desarrollo de Android y los autores de libros de Android se olvidó de eso?

+2

PreferenceManager.setDefaultValues ​​no implica SQL. SharedPreferences son todos archivos XML planos. –

+0

Sí, ha pasado una semana --- No recuerdo. He editado la pregunta para señalar que se trata de un acceso de archivo --- que es el mismo punto. Gracias por notar esto –

+0

Ahora en el emulador de Android 4.2.2, al usar 'PreferenceManager.setDefaultValues ​​(context, resId, readAgain)' al comenzar desde un subproceso generado _no_ el subproceso principal evitará que la actividad se infle con un seguimiento de pila larga que incluya "java". lang.RuntimeException: No se puede crear el controlador dentro de la cadena que no ha llamado a Looper.prepare() ". Por lo tanto, parece que no solo está bien acceder a los archivos en el hilo principal, sino que ahora es obligatorio en lo que respecta a establecer valores de preferencia predeterminados. –

Respuesta

8

La única manera que puedo ver es comenzar un hilo separado --- que introduce una condición de carrera con otro código de UI que podría leer las preferencias y esperar que los valores predeterminados ya estén establecidos.

Después, utilice un AsyncTask, poniendo la llamada setDefaultValues() en doInBackground() y el "otro código de interfaz de usuario que puede leer las preferencias" en onPostExecute().

Para obtener realmente información acerca de esa descarga (solo le da una ID de descarga), debe consultar el DownloadManager --- que implica un cursor, que le da un error si tiene una política estricta activada.

Así que consulta el DownloadManager en una cadena de fondo.

¿Cuál es la historia --- ¿está bien acceder a los cursores en el hilo principal?

Eso depende de su definición de "fino".

En Android 1.xy la mayoría de los dispositivos 2.x, el sistema de archivos utilizado es YAFFS2, que básicamente serializa todo el acceso al disco en todos los procesos. El efecto neto es que, si bien su código puede parecer lo suficientemente funcional de forma aislada, a veces parece lento en la producción debido a otras cosas que ocurren en segundo plano (por ejemplo, la descarga de un nuevo correo electrónico).

Si bien esto es un problema menos problemático en Android 3.xy versiones posteriores (cambiaron a ext4), no hay duda de que la E/S flash sigue siendo relativamente lenta; será un poco más predecible y lenta .

StrictMode está diseñado para indicar dónde puede producirse lentitud. Depende de usted determinar cuáles son benignos y cuáles no. En un mundo ideal, los limpiarías todos; en un mundo ideal, tendría pelo.

¿O es algo malo, y la mitad del equipo de desarrollo de Android y los autores de libros de Android se olvidó de eso?

Siempre ha sido una "mala cosa".

No puedo hablar de "la mitad del equipo de desarrollo de Android". Supongo que, al principio, esperaban que los desarrolladores aplicaran su experiencia de desarrollo existente para detectar un comportamiento lento: esto no es significativamente diferente de los problemas de rendimiento en cualquier otra plataforma. Con el tiempo, han estado ofreciendo más patrones para guiar a los desarrolladores en una ruta positiva (por ejemplo, el marco Loader), además de los cambios en el sistema (por ejemplo, YAFFS2-> ext4) para que esto no sea un problema. En parte, intentan abordar los lugares donde Android presenta distintos desafíos relacionados con el rendimiento, como la interfaz de usuario de subproceso único.

Del mismo modo, no puedo hablar de todos los autores de libros de Android. Ciertamente no me centré en los problemas de rendimiento en las primeras ediciones de mis libros, ya que me estaba centrando en las características y funciones de Android. Con el tiempo, he agregado más consejos en estas áreas. También contribuí con el código fuente abierto relacionado con estos temas. En 2012, haré revisiones masivas a mis libros y crearé más proyectos de fuente abierta para continuar abordando estos problemas. Sospecho, dado su tono, que yo (y probablemente otros) son fracasos completos a sus ojos en este aspecto, y sin duda es bienvenido su opinión.

+0

Gracias por la respuesta detallada, aunque todavía me siento un poco inestable --- No estoy seguro de si está en su respuesta o simplemente en la situación general. Pero no estoy seguro de que entendiste mi punto de establecer los valores de preferencia. ¿Qué pasa si el usuario es el botón "Hacer algo", cuya acción depende de la configuración de preferencias --- Supongo que tengo que comprobar un indicador establecido en InitPreferencesAsyncTask.OnPostExecute(), y si no está configurado mostrar un cuadro de diálogo, " No puedo hacer eso aún --- las preferencias no se han cargado ". De ahí el ímpetu de mi pregunta --- ¿Android está diseñado con anti-patrones de mierda, o me falta algo? –

+0

@GarretWilson: Está bastante claro que tu objetivo es atacar a las personas. Puedes hacerlo por ti mismo; No voy a jugar conmigo. – CommonsWare

+1

Por un segundo no tenía idea de a quién pensabas que estaba "atacando" --- después de todo, no tengo idea de quién diseñó la arquitectura de Android. Luego me di cuenta de que, como usted sugirió el uso de AsyncTask, debe estar asumiendo que lo estaba atacando. Este no era el caso, aunque no estaba seguro de haber entendido mi punto.Usted sugirió una solución alternativa a un problema, y ​​si estaba atacando algo, era el diseño de Android lo que requeriría una solución de este tipo. Todavía me parece que mi respuesta es simplemente lamentarme por el diseño de Android y preguntarme si me falta algo. Lo siento si lo tomó de otra manera. –

Cuestiones relacionadas