Singletons vs. Contexto de la aplicación en Android?

Recordando este post enumerando varios problemas de uso de singletons y habiendo visto varios ejemplos de aplicaciones de Android usando patrón singleton, me pregunto si es una buena idea usar Singletons en lugar de instancias únicas compartidas a través del estado de aplicación global (subclase android.os.Application y obtenerlo Mediante context.getApplication ()).

¿Qué ventajas / desventajas tendrían ambos mecanismos?

Para ser honesto, espero la misma respuesta en este post Singleton patrón con la aplicación web, No es una buena idea! Pero aplicado a Android. ¿Estoy en lo correcto? ¿Qué es diferente en DalvikVM de otra manera?

EDIT: Me gustaría tener opiniones sobre varios aspectos involucrados:

  • Sincronización
  • Reutilización
  • 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 los objetos ligeros, de ámbito de tarea, que pueden ser fácilmente recreados cuando los necesite.

Singletons son una pesadilla para la prueba y, si se inicializa perezosamente, introducirá "indeterminismo de estado" con sutiles efectos secundarios (que de repente pueden surgir al mover las llamadas a getInstance () de un ámbito a otro). La visibilidad se ha mencionado como otro problema, y ​​como los singletons implican un acceso "global" (= aleatorio) a un estado compartido, pueden surgir errores sutiles cuando no se sincronizan correctamente en aplicaciones concurrentes.

Considero que es un anti-patrón, es un mal estilo orientado a objetos que esencialmente equivale a mantener un estado global.

Para volver a su pregunta: Aunque el contexto de la aplicación puede considerarse un singleton en sí, está gestionado por el marco y tiene un ciclo de vida, alcance y ruta de acceso bien definidos. Por lo tanto, creo que si usted necesita administrar el estado de aplicación global, debe ir aquí, en ningún otro lugar. Para cualquier otra cosa, repensar si realmente necesita un objeto singleton o si también sería posible reescribir su clase singleton para instanciar objetos pequeños y de corta duración que realizan la tarea a mano.

Recomiendo mucho singletons. Si tiene un singleton que necesita un contexto, tenga:

MySingleton.getInstance(Context c) { // // ... needing to create ... sInstance = new MySingleton(c.getApplicationContext()); } 

Prefiero singletons sobre la aplicación, ya que ayuda a mantener una aplicación mucho más organizada y modular – en lugar de tener un lugar donde todo su estado global a través de la aplicación debe mantenerse, cada pieza por separado puede cuidar de sí mismo. También el hecho de que singletons perezosamente inicializar (a petición) en lugar de llevarlo por el camino de hacer toda la inicialización por adelantado en Application.onCreate () es bueno.

No hay nada intrínsecamente malo con el uso de singletons. Sólo usarlos correctamente, cuando tiene sentido. El framework de Android realmente tiene muchos de ellos, para que pueda mantener cachés por proceso de recursos cargados y otras cosas semejantes.

También para aplicaciones simples multithreading no se convierte en un problema con singletons, porque por diseño todas las devoluciones de llamada estándar a la aplicación se despachan en el hilo principal del proceso por lo que no tendrá multi-threading sucediendo a menos que lo introduzca explícitamente a través de hilos o Implícitamente mediante la publicación de un proveedor de contenido o servicio IBinder a otros procesos.

Sólo tenga en cuenta lo que está haciendo. 🙂

De: http://developer.android.com/reference/android/app/Application.html

Normalmente no es necesario subclasificar la Aplicación. En la mayoría de las situaciones, los singletons estáticos pueden proporcionar la misma funcionalidad de una manera más modular. Si su singleton necesita un contexto global (por ejemplo, para registrar receptores de radiodifusión), la función para recuperarla se puede dar un contexto que utiliza internamente Context.getApplicationContext () al construir primero el singleton.

La aplicación no es la misma que la Singleton. Las razones son:

  1. El método de la aplicación (como onCreate) se llama en el subproceso ui;
  2. El método de singleton puede ser llamado en cualquier hilo;
  3. En el método "onCreate" de Application, puede instanciar Handler;
  4. Si el singleton se ejecuta en el subproceso none-ui, no se puede instanciar Handler;
  5. La aplicación tiene la capacidad de gestionar el ciclo de vida de las actividades en la app.It tiene el método "registerActivityLifecycleCallbacks". Pero los singletons no tiene la capacidad.

Tuve el mismo problema: Singleton o hacer una subclase android.os.Application?

Primero probé con el Singleton pero mi aplicación en algún momento hace una llamada al navegador

 Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com")); 

Y el problema es que, si el teléfono no tiene suficiente memoria, la mayoría de sus clases (incluso Singletons) se limpian para obtener algo de memoria, al volver del navegador a mi aplicación, se estrelló cada vez.

Solución: coloque los datos necesarios dentro de una subclase de la clase de aplicación.

Considere ambos al mismo tiempo:

  • Teniendo objetos singleton como instancias estáticas dentro de las clases.
  • Tener una clase común (Context) que devuelve las instancias singleton para todos los objetos singelton en su aplicación, lo cual tiene la ventaja de que los nombres de métodos en Context serán significativos por ejemplo: context.getLoggedinUser () en lugar de User.getInstance ().

Además, sugiero que amplíe su Contexto para incluir no sólo el acceso a objetos singleton, sino algunas funcionalidades que necesitan ser accedidas globalmente, como por ejemplo: context.logOffUser (), context.readSavedData (), etc. Probablemente cambiando el nombre del Context a La fachada tendría sentido entonces.

En realidad son lo mismo. Hay una diferencia que puedo ver. Con la clase Application puede inicializar sus variables en Application.onCreate () y destruirlas en Application.onTerminate (). Con singleton tienes que confiar VM inicializar y destruir la estática.

Mi actividad llama a finish () (que no lo hace terminar inmediatamente, pero lo hará eventualmente) y llama a Google Street Viewer. Cuando la depuro en Eclipse, mi conexión a la aplicación se rompe cuando se llama a Street Viewer, que entiendo como la aplicación (completa) que se está cerrando, supuestamente para liberar memoria (ya que una sola actividad que está terminando no debería causar este comportamiento) . Sin embargo, puedo ahorrar el estado en un paquete vía onSaveInstanceState () y restaurarlo en el método onCreate () de la actividad siguiente en la pila. Ya sea utilizando una aplicación estática de singleton o subclase, me enfrento al cierre de la aplicación y al estado perdedor (a menos que lo guarde en un Bundle). Así que de mi experiencia son los mismos con respecto a la preservación del estado. Me di cuenta de que la conexión se pierde en Android 4.1.2 y 4.2.2, pero no en 4.0.7 o 3.2.4, que en mi entendimiento sugiere que el mecanismo de recuperación de memoria ha cambiado en algún momento.

Mis 2 centavos:

Me di cuenta de que algunos singleton / campos estáticos fueron reseted cuando mi actividad fue destruida. Me di cuenta de esto en algunos dispositivos de gama baja 2.3.

Mi caso fue muy simple: sólo tengo un archivo privado "init_done" y un método estático "init" que llamé de activity.onCreate (). Noto que el método init se estaba re-ejecutando en alguna recreación de la actividad.

Aunque no puedo probar mi afirmación, puede estar relacionada con CUANDO el singleton / clase fue creado / usado primero. Cuando la actividad se destruye / recicla, parece que todas las clases que sólo se refieren a esta actividad se reciclan también.

Moví mi instancia de singleton a una subclase de Application. Los accedo desde la instancia de la aplicación. Y, desde entonces, no notó el problema otra vez.

Espero que esto pueda ayudar a alguien.

De la boca proverbial del caballo …

Al desarrollar su aplicación, puede que sea necesario compartir datos, contexto o servicios globalmente en su aplicación. Por ejemplo, si su aplicación tiene datos de sesión, como el usuario actualmente conectado, es probable que desee exponer esta información. En Android, el patrón para resolver este problema es que la instancia de android.app.Application posea todos los datos globales y, a continuación, trate su instancia de aplicación como un singleton con accesores estáticos a los diversos datos y servicios.

Cuando escribes una aplicación para Android, solo tienes una instancia de la clase android.app.Application, por lo que es seguro (y recomendado por el equipo de Google Android) tratarla como un singleton. Es decir, puede añadir un método estático getInstance () a su implementación de aplicación. Al igual que…

 public class AndroidApplication extends Application{ private static AndroidApplication sInstance; public static AndroidApplication getInstance(){ return sInstance; } @Override public static void onCreate(){ super.onCreate() sInstance = this; } } 
  • Cómo separar la actividad principal y el selector de fechas con las propias clases
  • Acceso al objeto GoogleApiClient en Todas las actividades
  • Java.lang.IllegalStateException: La aplicación PagerAdapter cambió el contenido del adaptador sin llamar a PagerAdapter # notifyDataSetChanged android
  • Android: No se puede realizar esta operación porque se ha cerrado el grupo de conexiones
  • ¿Cuándo / por qué se destruye mi instancia de singleton de Java?
  • Clase de Aplicación SingleTon de Kotlin
  • Métodos estáticos o Singletons rendimiento-sabio (Android)?
  • Android Crittercism init tanto en la aplicación como en la actividad
  • Actividad de Android singleton
  • ¿Qué hace este método privado en esta clase singleton Java?
  • Android Singleton con un contexto global
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.