Indice
- Definición
- Como obtener el context
- Uso
- Utilizarlo en Composables
- Utilizarlo en ViewModels
- Referencias
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:
- Acceder a una base de datos
- Al sistema de notificaciones
- Al sistema de ficheros
- Lanzar actividades, servicios
- Trabajar con permisos
- 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")
}
}
}
La actividad principal, MainActivity
contiene un único Composable
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyComposable()
}
}
}
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")
}
}
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
}
}
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)
}
}
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
...
}
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
Top comments (0)