Acceder a objetos globales de la aplicación

Cada uno de los componentes de una aplicación se escribe en una clase separada. Esto hace que en muchas ocasiones resulte complicado compartir objetos entre estos componentes.
Para poder acceder a una información global desde cualquier clase de nuestro proyecto, podemos utilizar el modificador static. De esta forma, no será necesario conocer la referencia a un objeto de la clase, solo con indicar el nombre de la clase podremos acceder a esta información.
Otra alternativa, muy similar a la anterior, es utilizar el patrón Singleton. Una clase definida con este patrón solo dispondrá de una instancia a la que se podrá acceder desde cualquier sitio utilizando un método estático. Lo veremos más adelante.
Una tercera alternativa específica de Android consiste en crear un descendiente de la clase Application. En el siguiente punto se explica cómo hacerlo.
 

La clase Application

Esta clase ha sido creada en Android para almacenar información global a toda la aplicación.

video[Tutorial ] La clase Application en Android.

Veamos cómo usarla en tres pasos:

1.     Crea un descendiente de Applicaction que contenga la información global y los métodos asociados para acceder a esta información. Mira el ejemplo:

public class Aplicacion extends Application {
   private int saldo;
   @Override public void onCreate() {
      super.onCreate();
      SharedPreferences pref = getSharedPreferences("pref", MODE_PRIVATE);
      saldo = pref.getInt("saldo_inicial", -1);
   }

   public int getSaldo(){
      return saldo;
   }
	
   public void setSaldo(int saldo){
      this.saldo=saldo;
   }
}  
class Aplicacion : Application() {
   var saldo: Int = 0

   override fun onCreate() {
      super.onCreate()
      val pref = getSharedPreferences("pref", MODE_PRIVATE)
      saldo = pref.getInt("saldo_inicial", -1)
   }
} 

En nuestra aplicación queremos que el usuario disponga de un saldo de puntos, con los que podrá ir desbloqueando ciertas características especiales. La clase Application es descendiente de Context, por lo que tendremos acceso a todos los métodos relativos a nuestro contexto. Entre estos métodos se incluye getSharedPreferences, para acceder a un fichero de preferencias almacenado en la memoria interna de nuestra aplicación. La clase Application permite sobrescribir los siguientes:

  • -onCreate() llamado cuando se cree la aplicación. Puedes usarlo para inicializar los datos.
  • -onConfigurationChanged(Configuration nuevaConfig) llamado cuando se realicen cambios en la configuración del dispositivo, mientras que la aplicación se está ejecutando.
  • -onLowMemory() llamado cuando el sistema se está quedando sin memoria. Trata de liberar toda la memoria que sea posible.
  • -onTrimMemory(int nivel) (desde nivel API 14) llamado cuando el sistema  determina que es un buen momento para que una aplicación recorte memoria. Esto ocurrirá, por ejemplo, cuando está en el fondo de la pila de actividades y no hay suficiente memoria para mantener tantos procesos en segundo plano. Además, se nos pasa como parámetro el nivel de necesidad. Algunos valores posibles son: TRIM_MEMORY_COMPLETE, TRIM_MEMORY_BACKGROUND, TRIM_MEMORY_MODERATE, …


2.    Registra la clase creada en AndroidManifest. Para ello busca la etiqueta <application>  y añade el atributo name, con el nombre de la clase creada:

...
<application
      android:name="Aplicacion"
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme">
... 
3.    Puedes obtener una referencia a tu clase <application> con este código:

Aplicacion aplicacion = (Aplicacion) contexto.getApplication();
val aplicacion = contexto.application as Aplicacion
Donde contexto es una referencia a la clase Context. En caso de estar en un descendiente de esta clase (como Activity, Service,…) no es necesario disponer de esta referencia, la misma clase ya es un Context. Por lo tanto, podríamos escribir:
 
Aplicacion aplicacion = (Aplicacion) getApplication();
val aplicacion = application as Aplicacion
o incluso directamente:
int miSaldo = ((Aplicacion) getApplication()).getSaldo();
val miSaldo = (application as Aplicacion).saldo

Ejercicio: Añadir la clase Application en Mis Lugares.

1.     Abre el proyecto MisLugares.
2.     Vamos a empezar creando una nueva clase. Para ello pulsa con el botón derecho sobre el java / com.example.audiolibros y selecciona New > Java Class o New > Kotlin File / Class . Introduce como nombre de la clase Aplicacion. En ella vamos a almacenar dos objetos que queremos usar globalmente en toda la aplicación, vectorLibros y adaptador. Reemplaza su código por el siguiente:

public class Aplicacion extends Application {

  public RepositorioLugares lugares = new LugaresLista();
   @Override public void onCreate() {
      super.onCreate();
   }

   public Lugares getLugares() {
      return lugares;
   }
   public RepositorioLugares getLugares() {  Quitar
      return lugares;
   } 
} 
class Aplicacion : Application() {
   val lugares = LugaresLista()

} 
Nota: Tras incluir nuevas clases tendrás que indicar los imports adecuados. Pulsa «Alt+Intro» en Android Studio para que lo haga automáticamente. Aparecerá algún error dado que la clase Lugares aún no ha sido creadas. No te preocupes, lo haremos más adelante.

3.     Registra el nombre de la clase en AndroidManifest, añadiendo la línea que aparece en negrita.

<application
      android:name="Aplicacion"
      android:allowBackup="true"
      ...	

4.     En el primer capítulo se creó el proyecto MisLugaresJava/Kotlin. Abre este proyecto y selecciona las clases GeoPunto, Lugar, Lugares, LugaresLista y TipoLugar (puedes seleccionar varios ficheros manteniendo la tecla Ctrl pulsada). Con el botón derecho selecciona la opción Copy. Con el botón derecho pulsa sobre com.example.mislugares del proyecto MisLugares y selecciona la opción Paste.

5.     Puedes ejecutar el proyecto para verificar que sigue funcionando. No has de notar diferencias con respecto a la versión anterior, no hemos añadido nuevas funcionalidades.