remember — conceptos clave, conservación de valores entre recomposiciones

Autor: IT Sectr Publicado: 2026-06-28 Tiempo de lectura: 8 min

remember es una función en Jetpack Compose que permite conservar un valor entre recomposiciones, evitando el reinicio del estado en cada reinicio de una función Composable. Sin remember, todas las variables declaradas dentro de una función se reiniciarían en cada actualización de la interfaz de usuario, haciendo que el estado sea inestable e inútil. Según Google Android Developers, 2026, el uso correcto de remember es la base de una gestión de estado adecuada en UI declarativa.

Puntos Clave

  • remember conserva un valor en el slot de composición entre recomposiciones de la función
  • Las claves en remember(key) determinan cuándo se debe recalcular el valor
  • rememberSaveable conserva el valor al rotar la pantalla y minimizar la aplicación
  • derivedStateOf crea estado derivado, optimizando los cálculos durante la recomposición
  • El reinicio de remember solo ocurre cuando la función sale de la composición

Qué es remember en Jetpack Compose

remember es una función integrada de Jetpack Compose del paquete androidx.compose.runtime que crea un objeto que conserva su valor entre llamadas sucesivas de una función Composable. Técnicamente, remember funciona con slots — celdas de memoria especiales asignadas para cada posición de llamada de función en el árbol de UI. Mientras la función permanezca en la composición (no se elimine mediante una condición if), remember devolverá el valor guardado en cada recomposición.

La sintaxis de remember es simple: dentro de las llaves se especifica el bloque de cálculo del valor inicial. El bloque se ejecuta solo una vez — durante la primera composición de la función. Todas las recomposiciones posteriores devuelven el valor ya guardado sin volver a ejecutar el bloque. Sin embargo, si se especifica un parámetro clave, el bloque se vuelve a ejecutar cuando la clave cambia, lo que permite recalcular el valor basado en los datos de entrada.

remember no es magia de Kotlin — es una función simple con un parámetro clave y una lambda de cálculo. Su implementación interna utiliza Composer para leer y escribir en los slots. El compilador de Kotlin, al ver una llamada a remember, genera código que accede al CompositionContext actual y gestiona los slots. Esto significa que remember solo se puede llamar dentro de una función Composable u otra función en el contexto de composición.

Tipos de remember: remember, rememberSaveable, derivedStateOf

En Jetpack Compose, existen tres variantes principales de remember, cada una con su propósito. El remember básico solo conserva el valor en la memoria del proceso actual — al rotar la pantalla (config change), Compose recrea la Composition y todos los valores de remember se reinician. Para conservar datos durante cambios de configuración y detención del proceso se utiliza rememberSaveable.

rememberSaveable serializa el valor en un Bundle mediante el mecanismo SavedStateHandle o Parcelable. Esto permite sobrevivir a la rotación de pantalla, la configuración "No mantener actividades" e incluso la minimización temporal de la aplicación. Sin embargo, rememberSaveable impone restricciones sobre el tipo de datos que puede almacenar: deben ser primitivos, Parcelable, Serializable o soportar un convertidor Saver.

derivedStateOf no es un mecanismo de conservación sino una optimización. Crea un State cuyo valor se calcula a partir de otros objetos State. derivedStateOf reacciona a cambios en los estados fuente pero recalcula el valor solo cuando hay suscriptores. Si la recomposición actual no lee el derivedStateOf, el cálculo no se realiza, ahorrando recursos en actualizaciones frecuentes pero innecesarias.

kotlin
@Composable
fun RememberVariants() {
    // 1. Remember básico: persiste hasta salir de la composición
    val createdAt = remember { System.currentTimeMillis() }

    // 2. rememberSaveable: sobrevive a la rotación de pantalla
    var username by rememberSaveable { mutableStateOf("") }

    // 3. derivedStateOf: se calcula solo cuando es necesario
    val isButtonVisible = remember {
        derivedStateOf { username.length() > 3 }
    }

    Text("Creado: $createdAt")
    TextField(value = username, onValueChange = { username = it })

    if (isButtonVisible.value) {
        Text("El botón se mostrará")
    }
}

remember vs rememberSaveable: cuándo usar cada uno

La elección entre remember y rememberSaveable depende de qué tan crítico sea conservar los datos durante cambios de configuración. Para estados temporales que no es importante perder al rotar (animación, posición actual de desplazamiento, estado de foco) — el remember normal es suficiente. Para datos críticos (texto en formularios, elementos seleccionados, casillas de verificación) — use rememberSaveable.

Rendimiento: rememberSaveable es más lento que remember normal porque requiere serialización en un Bundle. Use rememberSaveable solo para datos que realmente necesiten sobrevivir a la recreación de Activity. Para todo lo demás — remember simple. El uso excesivo de rememberSaveable provoca ralentizaciones al rotar la pantalla y al cambiar entre aplicaciones.

Si trabaja con clases que no soportan Parcelable o Serializable, use Saver — un convertidor que define cómo guardar y restaurar el objeto. Saver se describe con un par de lambdas: save (convierte el objeto a un tipo almacenable) y restore (restaura el objeto a partir de los datos guardados). Ya existe un Saver estándar implementado para mutableStateListOf y mutableStateMapOf.

CaracterísticarememberrememberSaveable
Conservación durante recomposición
Conservación al rotarNo
Conservación al detener procesoNo
Requisitos de tipoCualquieraParcelable, Serializable, Saver
RendimientoAltoMedio

Ejemplos de uso de remember en proyectos reales

Considere un escenario típico — una pantalla de edición de perfil donde remember se usa para varios propósitos: almacenar el estado de los campos del formulario, calcular valores derivados y almacenar en caché operaciones computacionalmente costosas.

kotlin
data class ProfileUiState(
    val name: String = "",
    val bio: String = "",
    val isSaving: Boolean = false
)

@Composable
fun ProfileEditor() {
    var state by rememberSaveable { mutableStateOf(ProfileUiState()) }
    val isValid = remember {
        derivedStateOf { state.name.isNotBlank() && state.bio.length() <= 500 }
    }

    val bioWarning = remember(state.bio) {
        if (state.bio.length() > 400) {
            "${500 - state.bio.length} chars left"
        } else null
    }

    Column(modifier = Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = state.name,
            onValueChange = { state = state.copy(name = it) },
            label = { Text("Nombre") }
        )

        OutlinedTextField(
            value = state.bio,
            onValueChange = { state = state.copy(bio = it) },
            label = { Text("Acerca de") }
        )

        bioWarning?.let { Text(it, color = MaterialTheme.colorScheme.error) }

        Button(onClick = { /* save */ },
            enabled = isValid.value) {
            Text("Guardar")
        }
    }
}

En el ejemplo, el estado se guarda mediante rememberSaveable — el texto no se perderá al rotar la pantalla. isValid se calcula mediante derivedStateOf, lo que evita cálculos innecesarios durante las recomposiciones. bioWarning usa remember con la clave bio — es un cálculo costoso (opcional, para demostración) que se recalcula solo cuando bio cambia, no en cada recomposición.

Estados derivados y remember con claves

Los estados derivados son valores que se calculan a partir de otros objetos State. En lugar de calcularlos en cada recomposición y desperdiciar CPU en resultados idénticos, remember con derivedStateOf calcula el valor solo cuando las fuentes cambian. Esto es especialmente útil para filtrado, ordenación y agregación de datos.

remember con claves (remember(key) { calculation }) es otro mecanismo de optimización. Si la clave no ha cambiado desde la última recomposición, el bloque de cálculo no se ejecuta y se devuelve el valor en caché. Esto es conveniente para almacenar en caché objetos cuya creación es costosa: formateo de fechas, análisis JSON, creación de grandes colecciones inmutables.

kotlin
@Composable
fun SearchResults(allItems: List<Item>, query: String) {
    // derivedStateOf: el filtro se recalcula solo cuando las entradas cambian
    val filtered = remember {
        derivedStateOf {
            allItems.filter { it.title.contains(query, true) }
        }
    }

    // remember con clave: estadísticas formateadas se recalculan solo al cambiar la consulta
    val statsText = remember(query) {
        "Results for query \"$query\": ${filtered.value.size}"
    }

    Text(statsText)
    LazyColumn {
        items(filtered.value, key = { it.id }) { item ->
            Text(item.title)
        }
    }
}

filtered es un derivedStateOf que se recalcula automáticamente cuando cambian allItems o query. statsText usa remember(query) — el formateo costoso de cadenas se realiza solo cuando cambia la consulta de búsqueda. La combinación de derivedStateOf y remember con claves proporciona el máximo rendimiento: el estado derivado se calcula solo cuando es necesario y los objetos complejos se almacenan en caché hasta que la clave cambia.

Preguntas Frecuentes

Se puede usar remember fuera de una función Composable?

No, remember es una función del paquete compose.runtime que requiere un CompositionContext. Solo se puede llamar dentro de una función @Composable o dentro de otra función llamada desde una Composable. Para almacenar datos fuera de la composición, use ViewModel.

Qué sucede si no se especifica una clave en remember?

Sin una clave, remember ejecuta el bloque de cálculo solo una vez — durante la primera composición. Todas las recomposiciones posteriores devuelven el valor guardado. Si necesita recalcular el valor cuando los datos cambian, asegúrese de especificarlos como clave: remember(data) { compute(data) }.

Cómo forzar el reinicio de remember?

No hay una forma directa de reiniciar remember. La única forma es eliminar la función de la composición (por ejemplo, ocultándola con una condición if) y luego mostrarla nuevamente. Al volver a entrar, el bloque remember se ejecuta de nuevo, creando un nuevo valor inicial.

En qué se diferencia remember de ViewModel?

remember almacena el estado en un slot de función Composable y vive mientras la función esté en composición. ViewModel vive mientras dure el ciclo de vida de la pantalla. ViewModel se conserva al rotar y se usa para lógica de negocio. remember es para estado local de UI que no se necesita fuera de una sola función.

Funciona remember en componentes Preview?

Sí, remember funciona correctamente en funciones @Preview Composable porque Preview crea un CompositionContext completo. Sin embargo, rememberSaveable puede no funcionar correctamente en Preview porque SavedStateHandle puede estar ausente en el entorno de vista previa.

Resumen

  • remember conserva un valor en el slot de composición y sobrevive a las recomposiciones de la función
  • rememberSaveable adicionalmente conserva el valor al rotar la pantalla y detener el proceso
  • derivedStateOf crea estado derivado con cálculos diferidos
  • Las claves en remember(key) controlan el recálculo del valor en caché
  • El reinicio de remember solo ocurre cuando la función se elimina de la composición
  • Rendimiento: derivedStateOf y las claves previenen cálculos innecesarios durante la recomposición
  • Recomendación: use rememberSaveable para campos de entrada y remember + derivedStateOf para valores calculados

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también