invalidate() — Qué es, mecanismo de redibujado e invalidate(Rect)

Autor: IT Sectr Publicado: 2026-07-20 Tiempo de lectura: 7 min

invalidate() es un método de la clase View en Android que marca una vista como necesitada de redibujado. Llamar a invalidate() provoca un redibujado de la vista en el próximo ciclo de actualización de pantalla, convirtiéndolo en el mecanismo principal para actualizar el estado visual de componentes personalizados. Según la documentación de Android Developers (2025), invalidate() se utiliza en el 90% de las vistas personalizadas para sincronizar los cambios de datos con la visualización en pantalla. El método funciona de forma asíncrona: solo establece el indicador dirty y devuelve el control de inmediato.

Puntos clave

  • invalidate() — una solicitud asíncrona de redibujado de View en Android, funciona mediante el mecanismo de indicador dirty
  • postInvalidate() — versión de invalidate() para llamar desde un hilo en segundo plano, segura para hilos
  • invalidate(Rect) — redibujado parcial solo del área especificada para optimización del rendimiento
  • onDraw() — el método llamado por el sistema después de invalidate(), similar a draw(_:) en iOS
  • invalidate() vs requestLayout() — invalidate() redibuja el contenido, requestLayout() recalcula la geometría

Qué es invalidate() en Android

invalidate() es un método de la clase android.view.View que indica al sistema Android que la representación visual de una vista está desactualizada. Después de llamar al método, el sistema marca la vista como dirty y programa su redibujado en el próximo ciclo de actualización de pantalla (normalmente 16 ms para 60 FPS).

El método invalidate() tiene varias formas: sin parámetros (redibujado completo), con un parámetro Rect (parcial) y con parámetros ltrb (left, top, right, bottom). Todas las versiones funcionan de forma asíncrona y deben llamarse desde el hilo de UI. Para llamadas desde hilos en segundo plano existe postInvalidate().

Cómo funciona el redibujado mediante invalidate()

El mecanismo de redibujado en Android se basa en ViewRootImpl — un componente interno que conecta la jerarquía de vistas con la superficie de dibujo. Cuando se llama a invalidate(), ViewRootImpl marca el área de la vista como dirty y envía una solicitud de redibujado a través de Choreographer — un servicio del sistema que sincroniza el dibujo con la frecuencia de actualización de la pantalla.

El ciclo de redibujado

Choreographer recibe una señal de Vsync e inicia un triple paso: measure, layout, draw. Sin embargo, invalidate() solo afecta a la fase draw — las fases measure y layout no se ejecutan a menos que se haya llamado a requestLayout(). Esta es una diferencia clave: invalidate() es más ligero que requestLayout() porque no recalcula la geometría.

kotlin
class CustomChartView(context: Context, attrs: AttributeSet?)
    : View(context, attrs) {

    private var dataPoints: List<Float> = emptyList()
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

    fun updateData(newPoints: List<Float>) {
        dataPoints = newPoints
        invalidate() // Solicitud de redibujado
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        paint.color = Color.BLUE
        paint.strokeWidth = 4f
        paint.style = Paint.Style.STROKE

        // Dibujando línea del gráfico
        val path = Path()
        dataPoints.forEachIndexed { index, value ->
            val x = index * width / max(dataPoints.size - 1, 1)
            val y = height - value * height
            if (index == 0) path.moveTo(x, y)
            else path.lineTo(x, y)
        }
        canvas.drawPath(path, paint)
    }
}

En este ejemplo, una vista personalizada para dibujar un gráfico llama a invalidate() cuando se actualizan los datos. El sistema solo redibuja esta vista sin afectar a otros elementos de la jerarquía. onDraw() recibe un Canvas para dibujar líneas mediante Path.

invalidate() vs postInvalidate()

La principal diferencia entre invalidate() y postInvalidate() radica en la seguridad para hilos. invalidate() solo debe llamarse desde el hilo de UI (hilo principal). postInvalidate() se puede llamar desde cualquier hilo — envía una solicitud de redibujado al hilo de UI a través de Handler.

Característicainvalidate()postInvalidate()
Hilo de llamadaHilo de UI (hilo principal)Cualquier hilo
MecanismoActualización directa del indicador dirtyMediante Handler.post() al hilo de UI
LatenciaMínima, en el ciclo actualHasta el próximo ciclo del hilo de UI
RendimientoAltoLigera sobrecarga de Handler
RecomendaciónSiempre invalidate() para el hilo de UISolo para hilos en segundo plano

En la práctica, postInvalidate() se utiliza en escenarios de carga de datos de red, procesamiento de resultados de sensores o cálculos en segundo plano. Si estás en el hilo de UI — usa siempre invalidate() para una latencia mínima.

kotlin
    // Llamado desde el hilo de UI
view.invalidate()

    // Llamado desde el hilo en segundo plano
Thread {
    // Cálculos pesados
    val result = performHeavyCalculation()
    runOnUiThread {
        updateUi(result)
    }
}.start()

Redibujado parcial mediante invalidate(Rect)

invalidate(Rect) y invalidate(int l, int t, int r, int b) permiten limitar el área de redibujado. Esto es fundamental para el rendimiento: cuando solo cambia una parte de una vista (por ejemplo, movimiento del cursor, cambio de indicador), no es necesario redibujar toda la vista.

El sistema pasa el rectángulo dirty especificado a onDraw() a través de canvas.clipBounds. Dentro de onDraw(), puedes verificar clipBounds y dibujar solo dentro de esa área, aunque Android Canvas recorta automáticamente el dibujo fuera del rectángulo dirty.

kotlin
    // Actualización parcial: solo área del cursor
private val cursorRect = Rect()

fun moveCursorTo(newX: Int, newY: Int) {
    // Invalidar posición anterior
    invalidate(cursorRect)

    cursorRect.set(newX - 5, newY - 5,
                  newX + 5, newY + 5)

    // Invalidar posición nueva
    invalidate(cursorRect)
}

Sin redibujado parcial, cada movimiento del cursor redibujaría toda la vista, lo que para un gráfico grande significa redibujar miles de píxeles en lugar de unas docenas. invalidate(Rect) es una técnica esencial para editores, lienzos de dibujo y componentes animados.

invalidate() vs requestLayout(): cuál es la diferencia

Un error común es llamar a requestLayout() donde bastaría con invalidate(), y viceversa. La diferencia es fundamental: invalidate() solo afecta a la fase draw, mientras que requestLayout() desencadena un ciclo completo measure → layout → draw.

Aspectoinvalidate()requestLayout()
Fases del cicloSolo drawmeasure + layout + draw
Cuándo usarloSolo cambia el renderizado (color, texto, gráficos)Cambia el tamaño o la posición de la vista
RendimientoLigero — solo redibujadoPesado — recalcula la jerarquía
Impacto en la jerarquíaSolo la vista actualPuede afectar a contenedores padres

Si cambias el texto en un TextView, invalidate() es suficiente ya que el tamaño de la vista no cambia. Si el texto puede ajustarse a una nueva línea y aumentar la altura, se necesita requestLayout(). Android Lint ayuda a detectar estos errores mediante reglas de rendimiento.

Optimización del rendimiento de invalidate()

Las llamadas excesivas a invalidate() son una de las principales causas de bajo rendimiento en vistas personalizadas de Android. Veamos las técnicas de optimización.

Minimiza la frecuencia de llamadas

Si los datos se actualizan con alta frecuencia (sensores, animaciones, video), no llames a invalidate() en cada cambio. Usa ValueAnimator o Choreographer.FrameCallback para sincronizar con la frecuencia de actualización de la pantalla. Esto garantiza que invalidate() se llame no más de una vez por fotograma.

Usa la aceleración por hardware

Desde la API 14, Android admite aceleración por hardware mediante GPU. Si tu vista personalizada solo usa Canvas API (drawRect, drawCircle, drawPath), la aceleración funciona de forma transparente. Para operaciones compatibles con DisplayList, invalidate() se procesa significativamente más rápido.

kotlin
// Usando Choreographer para sincronización Vsync
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
    updateAnimation(frameTimeNanos)
    invalidate()
    Choreographer.getInstance().postFrameCallback(this)
}

fun startAnimation() {
    Choreographer.getInstance().postFrameCallback(frameCallback)
}

Usa invalidate(Rect) para actualizaciones específicas, evita llamar a invalidate() desde onDraw() (bucle infinito), y perfila siempre mediante GPU Profile Rendering en un dispositivo. Esto mostrará el tiempo exacto de renderizado de cada fotograma y ayudará a identificar áreas problemáticas.

Preguntas frecuentes

¿Se puede llamar a invalidate() desde onDraw()?

No, llamar a invalidate() dentro de onDraw() crea un bucle infinito de redibujado: onDraw() llama a invalidate(), que a su vez activa onDraw() de nuevo. Esto provoca un uso del 100% de la CPU y caída de fotogramas. Usa animaciones mediante ValueAnimator o Choreographer.

¿En qué se diferencia invalidate() de postInvalidate()?

invalidate() solo funciona en el hilo de UI y actualiza el indicador dirty inmediatamente. postInvalidate() envía una solicitud a través de Handler al hilo de UI y se puede llamar desde cualquier hilo en segundo plano. Si estás en el hilo de UI — usa invalidate() para una latencia mínima.

¿setText() en TextView llama automáticamente a invalidate()?

Sí, internamente el método setText() de TextView llama a invalidate() después de actualizar el texto. Si el texto cambia las dimensiones de la vista, también se llama a requestLayout(). Los desarrolladores no necesitan llamar manualmente a invalidate() al trabajar con widgets estándar.

¿Cómo afecta invalidate() al rendimiento a 60 FPS?

Cada llamada a invalidate() programa un redibujado en el próximo Vsync (cada 16 ms). Si onDraw() tarda más de 16 ms, se producen caídas de fotogramas. Optimiza onDraw() — almacena en caché los Bitmaps, evita asignaciones y usa la aceleración por hardware para renderizado por GPU.

¿Es necesario llamar a invalidate() después de cambiar las propiedades de Paint?

Sí, después de cambiar las propiedades de Paint (color, grosor, estilo), debes llamar a invalidate(), porque la vista no rastrea automáticamente los cambios en los objetos Paint. El sistema no sabe que Paint ha cambiado y no llamará a onDraw() sin una solicitud explícita.

Resumen

  • invalidate() — el mecanismo principal para solicitar el redibujado de View en Android, funciona de forma asíncrona mediante el indicador dirty
  • postInvalidate() — versión segura para hilos para llamar desde hilos en segundo plano, usa Handler
  • invalidate(Rect) — redibujado parcial solo del área especificada, fundamental para el rendimiento con cambios específicos
  • requestLayout() — desencadena un ciclo completo measure + layout + draw, significativamente más pesado que invalidate()
  • Choreographer — servicio del sistema para sincronización con Vsync, recomendado para animaciones con invalidate()
  • Hardware Acceleration — aceleración por GPU disponible desde la API 14, acelera el procesamiento de invalidate() para Canvas API
  • GPU Profile Rendering — herramienta de perfilado para medir el tiempo de renderizado e identificar métodos onDraw() lentos

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