DEV Community

Cover image for Context en Android
disced
disced

Posted on

Context en Android

Context en Android infografia resumen


Indice


Definición

Es una clase abstracta que la implementa Android, y cuya función es proporcionar acceso al entorno de la aplicación.

Así se define en la documentación oficial pero en mi caso no entiendo a que se refiere.

Si tenemos acceso al entorno de la aplicación, vamos a tener acceso a las siguientes funciones:

  1. Acceder a una base de datos
  2. Al sistema de notificaciones
  3. Al sistema de ficheros
  4. Lanzar actividades, servicios
  5. Trabajar con permisos
  6. Mostrar cuadros de diálogo

Como obtener el Context

La obtención del Context se puede realizar desde varios puntos en una app:

  • Desde cualquier Activity
  • Desde un Service
  • Desde cualquier View (si utilizas el modelo xml)
  • Desde cualquier Composable
  • O cualquier clase que extienda de Context

Existen dos métodos para acceder al contexto. Cada uno de ellos devuelve un contexto diferente y las principales diferencias son las siguientes:

getContext() (en views xml) getApplicationContext()
Contexto ligado a la Activity Contexto ligado a toda la Aplicación
Depende del ciclo de vida de la Activity Depende del ciclo de vida de la Aplicacion
Si muere la activty el context tambien Todas las actividades tienen acceso al mismo contexto (aparte del suyo propio)
Cada activty tiene el suyo propio

Usos

A continuación detallaré como se utiliza el context para varias tareas.

Iniciar Activity

Si vamos a iniciar una actividad diferente a la que se está ejecutando, deberemos hacer uso del Context.

En el ejemplo accederemos al context desde un Composable, en dicho composable tendremos acceso al contexto de la activity (es decir que dependerá del lifecycle de la activity) utilizando LocalContext.current.

Por ejemplo vamos a querer ejecutar en determinado momento la actvity SecondActivity

class SecondActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  

        setContent {  
            Text("Esta es la segunda actividad")  
        }  
    }  
}
Enter fullscreen mode Exit fullscreen mode

La actividad principal, MainActivity contiene un único Composable

class MainActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  

        setContent {  
            MyComposable()  
        }  
    }  
}
Enter fullscreen mode Exit fullscreen mode

La implementación del Composable que se utiliza en la actividad principal:

@Composable  
fun MyComposable() {  
    val context = LocalContext.current  

    Button(onClick = {  val intent = 
        Intent(context, SecondActivity::class.java)  
        context.startActivity(intent) }
    ) {  
        Text("Iniciar Activity")  
    }  
}
Enter fullscreen mode Exit fullscreen mode

En este ejemplo nuestro composable tiene un botón cuya única función es obtener el contexto y ejecutar la SecondActivity.

Al ejecutarse accedemos al contexto vinculado a la activity para poder iniciar una segunda actividad en caso de que el usuario pulse el botón.

Si se ha iniciado la segunda actividad y, por cualquier motivo, el SO decide detener la primera actividad, el contexto utilizado en MyComposable dejará de ser válido. Por este motivo, es importante evitar enviar el mismo contexto a la segunda actividad (mediante un Bundle), para prevenir posibles problemas relacionados con la gestión incorrecta del ciclo de vida del contexto y posibles fugas de memoria.

En Jetpack Compose se suele utilizar una única actividad para la aplicación.


Iniciar Servicios

Si queremos ejecutar un servicio en segundo plano (background) o en primer plano (foreground) también usaremos el Context.

Tenemos el siguiente servicio:

class MyBackgroundService : Service() {  
    override fun onBind(intent: Intent?): IBinder? {  
        return null  
    }  

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {  
        // { ... la logica del servicio }  
        return START_STICKY  
    }  
}
Enter fullscreen mode Exit fullscreen mode

Su ejecución dentro de una actividad sería de la siguiente forma

class MainActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  

        // Iniciar el servicio  
        val intent = Intent(this, MyBackgroundService::class.java)  

        startService(intent)  
    }  
}
Enter fullscreen mode Exit fullscreen mode

En este caso el contexto lo utilizamos para instanciar un Intent (que este a su vez ejecutará el servicio). El primer parámetro del Intent es el contexto, como ComponentActivity extiende de la clase Context, se puede referenciar la misma clase (MainActivity) mediante this.


Utilizarlo en Composables

En el apartado Iniciar Activity se muestra como utilizar el contexto dentro de un composable, la implementación es de la siguiente forma:

@Composable  
fun MyComposable() {  
    val context = LocalContext.current  
    ...
}
Enter fullscreen mode Exit fullscreen mode

Esta es la forma en la que accedemos al contexto dentro de un composable, dicha forma nos devolverá el contexto ligado a la activity a la que pertenece dicho composable.


Utilizarlo en ViewModels

Al utilizar el patrón de diseño MVVM no deberíamos utilizar el Context dentro del ViewModel ya que podría haber fugas de memoria y otra razón es mantener la separación de responsabilidades. También nos ayuda a mantener el código y testearlo mucho mas fácil.

El ViewModel solo debe encargarse de almacenar datos relacionados con la vista (el composable) y manejar los datos de la vista pero sin implementar el manejo de dichos datos.

Es decir que él no debe manejar el acceso a una API o una BBDD o a cualquier recurso del sistema Android.

El ViewModel solo implementará la lógica ligada a la IU y la implementación la hará un Repository y el ViewModel hará uso del Repository.

Si se necesita utilizar el context dentro del ViewModel se hará de la misma forma, con un Repository que implemente las acciones necesarias y en el ViewModel se utilizará el Repository (inyectándolo por ejemplo).

PRACTICA POCO RECOMENDADA!

Si realmente quieres utilizarlo dentro del ViewModel puedes utilizar inyección de dependencias con Hilt por ejemplo e inyectar el Context en el ViewModel


Referencias

Context In Android Application

In this blog, we will learn about the context in Android application.

favicon amitshekhar.me

Top comments (0)