Flows de Kotlin para implementar búsquedas en tiempo real
Antonio Leiva

En Android, los Flows de Kotlin son una manera de representar secuencias de datos asincrónicas que emiten valores de forma continua.

Estos Flows pueden ser útiles en situaciones en las que deseamos escuchar eventos y procesar los resultados de forma asíncrona, como en el caso de una búsqueda en tiempo real.

Implementar búsqueda al escribir sobre un EditText

Para implementar una búsqueda en tiempo real en Android que escuche los eventos de un EditText y evite que se produzcan muchas consultas de búsqueda en un corto período de tiempo, podemos utilizar la función debounce de Kotlin.

Esta función nos permite filtrar eventos que lleguen demasiado rápido uno detrás de otro, permitiéndonos especificar un tiempo mínimo que debe transcurrir entre eventos para que sean emitidos al Flow.

Para utilizar el debounce con los Flows de Kotlin, podemos seguir los siguientes pasos:

Creamos una función de extensión para escuchar los cambios

Creamos una función de extensión sobre la clase EditText que devuelva un Flow con los cambios de texto del EditText.

Podemos hacer esto utilizando el método callbackFlow de Kotlin, que nos permite crear un Flow que se alimenta de callbacks.

fun EditText.textChanges(): Flow<CharSequence> {
    return callbackFlow {
        val textWatcher = object : TextWatcher {
            override fun afterTextChanged(s: Editable?) = Unit

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // este método se llama cuando el texto está cambiando
                trySend(s) // emitimos el valor al Flow
            }
        }
        addTextChangedListener(textWatcher)
        awaitClose {
            removeTextChangedListener(textWatcher)
        }
    }
}

Emitir valores solo si ha pasado cierto tiempo

Ahora podemos utilizar la función de extensión que hemos creado para obtener un Flow con los cambios de texto del EditText.

A continuación, aplicamos la función debounce al Flow para especificar un tiempo mínimo que debe transcurrir entre eventos para que sean emitidos.

val editText = EditText(context)

editText.textChanges()
    .debounce(500) // espere 500ms sin eventos para emitir el valor
    .onEach { text ->
        println("Texto actual: $text")
    }
    .launchIn(uiScope)

Con esto, cada vez que el usuario cambie el texto del EditText, se emitirá un evento al Flow.

Sin embargo, si el usuario escribe rápidamente y produce varios cambios de texto en menos de 500ms, solo se emitirá el último evento después de que hayan pasado 500ms sin nuevos cambios de texto.

Por último, podemos utilizar el Flow para realizar una búsqueda en tiempo real utilizando una API de búsqueda o cualquier otra lógica de procesamiento que necesitemos. Por ejemplo:

val editText = EditText(context)

editText.textChanges()
    .debounce(500) // espere 500ms sin eventos para emitir el valor
    .map { text -> text.toString() } // convertimos el CharSequence a String
    .filter { text -> text.isNotEmpty() } // filtramos los valores vacíos
    .distinctUntilChanged() // evitamos hacer búsquedas repetidas
    .flatMapLatest { query ->
        searchApi.search(query) // hacemos la búsqueda utilizando la API de búsqueda
            .asFlow() // convertimos el resultado a un Flow
    }
    .onEach { result ->
        println("Resultado de la búsqueda: $result")
    }
    .launchIn(uiScope)

Con esto, cada vez que el usuario escriba en el EditText y hayan pasado 500ms sin nuevos cambios de texto, se realizará una búsqueda utilizando la API de búsqueda y se mostrará el resultado en la consola.

Conclusión

En conclusión, los Flows de Kotlin son una herramienta útil para representar secuencias de datos asincrónicas en Android y pueden ser utilizados para implementar funcionalidades como la búsqueda en tiempo real.

Al utilizar la función debounce, podemos filtrar eventos que lleguen demasiado rápido uno detrás de otro y especificar un tiempo mínimo que debe transcurrir entre eventos para que sean emitidos al Flow.

De esta manera, podemos evitar que se produzcan muchas consultas de búsqueda en un corto período de tiempo y mejorar el rendimiento de nuestra aplicación.

Quizá también te interese…

¿Qué es Kotlin Multiplataforma?

¿Qué es Kotlin Multiplataforma?

En el mundo actual, donde los dispositivos móviles están presentes en nuestra vida diaria, es fundamental para los desarrolladores crear aplicaciones que se adapten a diferentes sistemas operativos. Kotlin Multiplataforma es una herramienta que facilita la creación de...

5 trucos de Kotlin para escribir código más eficiente en Android

5 trucos de Kotlin para escribir código más eficiente en Android

El lenguaje de programación Kotlin se ha convertido en el más popular para el desarrollo de aplicaciones de Android en los últimos años. Su sintaxis concisa y moderna, junto con su capacidad para mejorar la eficiencia de código, lo convierten en una opción atractiva...

Cómo crear un backend en Kotlin usando Ktor

Cómo crear un backend en Kotlin usando Ktor

Ktor es un framework de servidor web ligero y rápido para Kotlin, desarrollado por JetBrains. Es ideal para crear aplicaciones web y servicios RESTful, y es muy fácil de usar y configurar. En este artículo, vamos a ver cómo crear un backend para una aplicación de...

0 comentarios

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de DevExpert, S.L.U., con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad *