Saltar la navegación

3.2.2. Context

Como se ha visto anteriormente, lo más importante de las clases del SDK de Android, es el ciclo de vida. Muchos errores de programación Android son debidos a un descuido en el ciclo de vida tanto de actividades como de fragmentos, servicios y otros componentes del sistema operativo.

Estos componentes tienen lo que se denomina un contexto, que es una especie de identificador del recurso. De hecho, una clase Activity hereda de la clase Context a través de una larga cadena de subclases.

En palabras más precisas, Context se considera una clase abstracta que nosotros como desarrolladores, directamente, no podemos crear, debido a que es uno de los objetos que crea el propio sistema como, por ejemplo, sucede con los Activities. Muchos de los componentes que se suelen utilizar en el desarrollo de una app Android son heredados de clases context.

La clase context se utiliza para la obtención de recursos específicos de la aplicación; no obstante, es oportuno resaltar que existen diferentes tipos de lo qué es context en Android. Estos tipos son:

  • Application.
  • Activity.
  • Service.
  • BroadCastReciver.
  • ContentProvider.

Cada uno de estos objetos tiene una información diferente de modo que, dependiendo de cuándo o dónde lo vayamos a utilizar, nos va a dar una información u otra.

Por ejemplo, si quieres implementar un context para conocer si el dispositivo se encuentra en posición vertical o en posición horizontal, llamas al context del activity y obtienes dicha información, mientras que en el context application no puedes acceder a ella.

Descuido en el Context

Para comprobar cómo un descuido con los contextos puede ser un gran problema, añade el siguiente código sobrescribiendo la función onResume para que se cambie el texto cuando la actividad vuelva a ser visible:

override fun onResume() {
    super.onResume()
    tvSaludo.text = "Ahora el contexto es: $this"   // Cambio el texto
    Log.e("MainActivity", "Ahora el contexto es: $this")
}

Lanza la aplicación al terminal y rota el terminal. Observa que el identificador ha cambiado. Esto se debe a que, cada vez que rotamos el móvil, el giroscopio o acelerómetro integrado en el terminal avisarán al sistema operativo de que la orientación de la pantalla ha cambiado. El sistema reliza en ese momento lo siguiente:

  1. preguntará a la app cómo desea adaptarse al cambio de formato de portrait a landscape, o viceversa.
  2. Por defecto, la actividad será destruida y recreada con la nueva configuración de pantalla.
  3. Lo mismo ocurriría con otros cambios del sistema, podemos adaptarnos a ellos o dejar que el sistema operativo destruya y vuelva a construir la actividad.

Esto no ocurre cuando llevamos la aplicación a background y la volvemos a activar.  ¿Qué ocurriría si almacenásemos el contexto en una variable e intentásemos utilizarla más tarde sin tener en cuenta el ciclo de vida de la actividad? Pues que estaríamos utilizando un contexto desfasado.

Si ejecutamos este código y rotamos el terminal, veremos que el contexto ya no es el mismo que era antes de la rotación. Una vez más, debemos tener cuidado y respetar el ciclo de vida de los componentes del sistema Android.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if(contexto == null)
        contexto = this
    }
    override fun onResume() {
        super.onResume()
        tvSaludo.text = "Son iguales los contextos: ${this == contexto}"
        Log.e("MainActivity", "Son iguales los contextos: ${this == contexto}")
    }
    companion object {
        private var contexto: Context? = null
    }
}

Creado con eXeLearning (Ventana nueva)