Job en android kotlin
1. Introducción Breve: ¿Qué es un Job?
En el mundo de las Corrutinas de Kotlin (que son como hilos de ejecución súper ligeros), un Job es simplemente un manejador o un “recibo” de una tarea que se está ejecutando en segundo plano.
Piénsalo como el ticket que te dan cuando dejas ropa en la lavandería: ese ticket te permite saber si la ropa está lista, si se está lavando o, si decides que ya no la quieres, usarlo para cancelar el pedido. Un Job te da control total sobre la vida de tu tarea en segundo plano.
2. Ejemplo de Aplicación en el Mundo Real
Imagina que estás construyendo una aplicación de edición de fotos.
-
El usuario aplica un filtro complejo a una imagen de alta resolución.
-
Esta operación tarda unos segundos y se ejecuta en segundo plano para no congelar la pantalla.
-
De repente, el usuario decide que no le gusta cómo está quedando y presiona el botón “Cancelar” o retrocede a la pantalla anterior.
Sin un Job, la aplicación seguiría gastando batería y procesador terminando de aplicar el filtro, aunque el resultado ya no se vaya a mostrar.
Con un Job, simplemente llamamos a cancel() en el manejador de la tarea, y esta se detiene inmediatamente, ahorrando recursos valiosos del dispositivo.
3. El ‘Por qué’ y el ‘Cómo’
¿Por qué usarlo?
Principalmente por eficiencia y seguridad de memoria. En Android, las pantallas (Activities/Fragments) se destruyen y recrean frecuentemente (por ejemplo, al rotar el teléfono). Si lanzas una tarea pesada y la pantalla se destruye, necesitas detener esa tarea para evitar que intente actualizar una pantalla que ya no existe (lo que causaría un error/crash) o que consuma recursos innecesariamente.
¿Cómo se implementa? (Utilizando las mejores prácticas con ViewModel)
Aquí tienes un ejemplo funcional y limpio:
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
class MiViewModel : ViewModel() {
// 1. Creamos una variable para guardar la referencia al Job
private var miTareaJob: Job? = null
fun iniciarDescargaLarga() {
// 2. Si ya había una tarea corriendo, la cancelamos antes de empezar una nueva
// Esto evita tener múltiples tareas idénticas duplicadas.
miTareaJob?.cancel()
// 3. 'viewModelScope.launch' inicia una corrutina y DEVUELVE un Job.
// viewModelScope se encarga de cancelar todo si el ViewModel se destruye.
miTareaJob = viewModelScope.launch(Dispatchers.IO) {
println("Tutor Tec: Tarea iniciada en: ${Thread.currentThread().name}")
try {
// Simulamos un trabajo largo (ej. descargar un archivo grande)
// Usamos delay en lugar de Thread.sleep para no bloquear
repeat(5) { i ->
println("Tutor Tec: Procesando parte $i...")
delay(1000) // Espera 1 segundo de forma no bloqueante
}
println("Tutor Tec: ¡Tarea finalizada con éxito!")
} catch (e: CancellationException) {
// 4. Si la tarea es cancelada, la corrutina lanza esta excepción específica.
// Aquí puedes hacer limpieza si es necesario.
println("Tutor Tec: La tarea fue cancelada correctamente. Limpiando recursos...")
}
}
}
fun cancelarDescargaManualmente() {
// 5. Simplemente llamamos a cancel() sobre nuestra referencia al Job.
println("Tutor Tec: Cancelando la tarea manualmente por petición del usuario.")
miTareaJob?.cancel()
}
}
Comentarios
Publicar un comentario