¿Singletons versus contexto de aplicación en Android?
Recordando esta publicación que enumera varios problemas del uso de singletons y habiendo visto varios ejemplos de aplicaciones de Android que usan el patrón singleton, me pregunto si es una buena idea usar Singletons en lugar de instancias únicas compartidas a través del estado global de la aplicación (subclasificando android.os.Application y obteniéndolo a través de context.getApplication()).
¿Qué ventajas/inconvenientes tendrían ambos mecanismos?
Para ser honesto, espero la misma respuesta en esta publicación Patrón Singleton con aplicación web. ¡No es una buena idea! pero aplicado a Android. ¿Estoy en lo correcto? ¿Qué hay de diferente en DalvikVM?
EDITAR: Me gustaría tener opiniones sobre varios aspectos involucrados:
- Sincronización
- Reutilizabilidad
- Pruebas
Estoy muy en desacuerdo con la respuesta de Dianne Hackborn. Estamos eliminando poco a poco todos los singletons de nuestro proyecto en favor de objetos livianos con alcance de tarea que se pueden recrear fácilmente cuando realmente los necesite.
Los singletons son una pesadilla para las pruebas y, si se inicializan de forma perezosa, introducirán un "indeterminismo de estado" con efectos secundarios sutiles (que pueden surgir repentinamente al mover llamadas getInstance()
de un ámbito a otro). La visibilidad se ha mencionado como otro problema, y dado que los singleton implican un acceso "global" (= aleatorio) al estado compartido, pueden surgir errores sutiles cuando no se sincronizan correctamente en aplicaciones concurrentes.
Lo considero un antipatrón, es un mal estilo orientado a objetos que esencialmente equivale a mantener el estado global.
Para volver a tu pregunta:
Aunque el contexto de la aplicación puede considerarse un singleton en sí mismo, está administrado por el marco y tiene un ciclo de vida , un alcance y una ruta de acceso bien definidos. Por lo tanto, creo que si necesita administrar el estado global de la aplicación, debería ir aquí, en ningún otro lugar. Para cualquier otra cosa, reconsidere si realmente necesita un objeto singleton, o si también sería posible reescribir su clase singleton para crear instancias de objetos pequeños y de corta duración que realicen la tarea en cuestión.
Recomiendo mucho los singleton. Si tiene un singleton que necesita un contexto, tenga:
MySingleton.getInstance(Context c) {
//
// ... needing to create ...
sInstance = new MySingleton(c.getApplicationContext());
}
Prefiero los singletons a la Aplicación porque ayuda a mantener una aplicación mucho más organizada y modular: en lugar de tener un lugar donde se debe mantener todo el estado global de la aplicación, cada pieza separada puede cuidarse sola. Además, el hecho de que los singleton se inicialicen de manera perezosa (a pedido) en lugar de guiarlo por el camino de realizar toda la inicialización por adelantado en Application.onCreate() es bueno.
No hay nada intrínsecamente malo en utilizar singletons. Úselos correctamente, cuando tenga sentido. El marco de Android en realidad tiene muchos de ellos, para mantener cachés por proceso de recursos cargados y otras cosas similares.
Además, para aplicaciones simples, el subproceso múltiple no se convierte en un problema con los singleton, porque, por diseño, todas las devoluciones de llamada estándar a la aplicación se envían en el subproceso principal del proceso, por lo que no se producirá subproceso múltiple a menos que lo introduzca explícitamente a través de subprocesos o implícitamente mediante la publicación de un proveedor de contenido o servicio IBinder en otros procesos.
Sólo piensa en lo que estás haciendo. :)