invalidate() — O que é, mecanismo de redesenho e invalidate(Rect)

Autor: IT Sectr Publicado: 2026-07-20 Tempo de leitura: 7 min

invalidate() é um método da classe View no Android que marca uma view como precisando ser redesenhada. Chamar invalidate() desencadeia um redesenho da view no próximo ciclo de atualização da tela, tornando-o o principal mecanismo para atualizar o estado visual de componentes personalizados. Segundo a documentação do Android Developers (2025), invalidate() é usado em 90% das Views personalizadas para sincronizar alterações de dados com a exibição na tela. O método funciona de forma assíncrona — ele apenas define a flag dirty e retorna o controle imediatamente.

Principais pontos

  • invalidate() — uma solicitação assíncrona para redesenhar View no Android, funciona através do mecanismo de flag dirty
  • postInvalidate() — versão de invalidate() para chamar de uma thread em segundo plano, thread-safe
  • invalidate(Rect) — redesenho parcial apenas da área especificada para otimização de desempenho
  • onDraw() — o método chamado pelo sistema após invalidate(), semelhante a draw(_:) no iOS
  • invalidate() vs requestLayout() — invalidate() redesenha o conteúdo, requestLayout() recalcula a geometria

O que é invalidate() no Android

invalidate() é um método da classe android.view.View que informa ao sistema Android que a representação visual de uma view está desatualizada. Após chamar o método, o sistema marca a view como dirty e agenda seu redesenho no próximo ciclo de atualização da tela (normalmente 16 ms para 60 FPS).

O método invalidate() vem em várias formas: sem parâmetros (redesenho completo), com um parâmetro Rect (parcial) e com parâmetros ltrb (left, top, right, bottom). Todas as versões funcionam de forma assíncrona e devem ser chamadas da thread de UI. Para chamadas de threads em segundo plano, existe postInvalidate().

Como funciona o redesenho através de invalidate()

O mecanismo de redesenho no Android é baseado em ViewRootImpl — um componente interno que conecta a hierarquia de views à superfície de desenho. Quando invalidate() é chamado, ViewRootImpl marca a área da view como dirty e envia uma solicitação de redesenho através de Choreographer — um serviço do sistema que sincroniza o desenho com a taxa de atualização da tela.

O ciclo de redesenho

Choreographer recebe um sinal de Vsync e inicia uma tripla passagem: measure, layout, draw. No entanto, invalidate() afeta apenas a fase draw — as fases measure e layout não são executadas a menos que requestLayout() tenha sido chamado. Esta é uma diferença chave: invalidate() é mais leve que requestLayout() porque não recalcula a geometria.

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() // Solicitação de redesenho
    }

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

        // Desenhando linha do 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)
    }
}

Neste exemplo, uma View personalizada para desenhar um gráfico chama invalidate() quando os dados são atualizados. O sistema apenas redesenha esta View sem afetar outros elementos na hierarquia. onDraw() recebe um Canvas para desenhar linhas através de Path.

invalidate() vs postInvalidate()

A principal diferença entre invalidate() e postInvalidate() está na segurança de threads. invalidate() deve ser chamado apenas da thread de UI (thread principal). postInvalidate() pode ser chamado de qualquer thread — ele envia uma solicitação de redesenho para a thread de UI através de Handler.

Característicainvalidate()postInvalidate()
Thread de chamadaThread de UI (thread principal)Qualquer thread
MecanismoAtualização direta da flag dirtyVia Handler.post() para a thread de UI
LatênciaMínima, no ciclo atualAté o próximo ciclo da thread de UI
DesempenhoAltoPequena sobrecarga do Handler
RecomendaçãoSempre invalidate() para a thread de UIApenas para threads em segundo plano

Na prática, postInvalidate() é usado em cenários de carregamento de dados de rede, processamento de resultados de sensores ou cálculos em segundo plano. Se você está na thread de UI — use sempre invalidate() para latência mínima.

kotlin
    // Chamado da thread de UI
view.invalidate()

    // Chamado da thread em segundo plano
Thread {
    // Cálculos pesados
    val result = performHeavyCalculation()
    runOnUiThread {
        updateUi(result)
    }
}.start()

Redesenho parcial através de invalidate(Rect)

invalidate(Rect) e invalidate(int l, int t, int r, int b) permitem limitar a área de redesenho. Isso é crítico para o desempenho: quando apenas parte de uma View muda (por exemplo, movimento do cursor, alteração de indicador), não há necessidade de redesenhar a view inteira.

O sistema passa o retângulo dirty especificado para onDraw() através de canvas.clipBounds. Dentro de onDraw(), você pode verificar clipBounds e desenhar apenas dentro dessa área, embora o Android Canvas recorte automaticamente o desenho fora do retângulo dirty.

kotlin
    // Atualização parcial: apenas área do cursor
private val cursorRect = Rect()

fun moveCursorTo(newX: Int, newY: Int) {
    // Invalidar posição antiga
    invalidate(cursorRect)

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

    // Invalidar nova posição
    invalidate(cursorRect)
}

Sem redesenho parcial, cada movimento do cursor redesenhearia a View inteira, o que para um gráfico grande significa redesenhar milhares de pixels em vez de algumas dezenas. invalidate(Rect) é uma técnica essencial para editores, canvases de desenho e componentes animados.

invalidate() vs requestLayout(): qual a diferença

Um erro comum é chamar requestLayout() onde invalidate() seria suficiente, e vice-versa. A diferença é fundamental: invalidate() afeta apenas a fase draw, enquanto requestLayout() desencadeia um ciclo completo measure → layout → draw.

Aspectoinvalidate()requestLayout()
Fases do cicloApenas drawmeasure + layout + draw
Quando usarApenas a renderização muda (cor, texto, gráficos)O tamanho ou posição da view muda
DesempenhoLeve — apenas redesenhoPesado — recalcula a hierarquia
Impacto na hierarquiaApenas a view atualPode afetar contêineres pai

Se você alterar o texto em um TextView, invalidate() é suficiente, pois o tamanho da view não muda. Se o texto pode quebrar em uma nova linha e aumentar a altura, requestLayout() é necessário. Android Lint ajuda a rastrear esses erros através de regras de desempenho.

Otimização de desempenho de invalidate()

Chamadas excessivas a invalidate() são uma das principais causas de baixo desempenho em Views personalizadas no Android. Vamos ver as técnicas de otimização.

Minimize a frequência de chamadas

Se os dados são atualizados com alta frequência (sensores, animações, vídeo), não chame invalidate() em cada alteração. Use ValueAnimator ou Choreographer.FrameCallback para sincronizar com a taxa de atualização da tela. Isso garante que invalidate() seja chamado no máximo uma vez por quadro.

Use aceleração de hardware

Desde a API 14, o Android suporta aceleração de hardware via GPU. Se sua View personalizada usa apenas Canvas API (drawRect, drawCircle, drawPath), a aceleração funciona de forma transparente. Para operações compatíveis com DisplayList, invalidate() é processado significativamente mais rápido.

kotlin
// Usando Choreographer para sincronização Vsync
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
    updateAnimation(frameTimeNanos)
    invalidate()
    Choreographer.getInstance().postFrameCallback(this)
}

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

Use invalidate(Rect) para atualizações direcionadas, evite chamar invalidate() de onDraw() (loop infinito), e sempre faça perfil através de GPU Profile Rendering em um dispositivo. Isso mostrará o tempo exato de renderização de cada quadro e ajudará a identificar áreas problemáticas.

Perguntas frequentes

Pode-se chamar invalidate() de onDraw()?

Não, chamar invalidate() dentro de onDraw() cria um loop infinito de redesenho: onDraw() chama invalidate(), que aciona onDraw() novamente. Isso leva a 100% de uso da CPU e queda de quadros. Use animações através de ValueAnimator ou Choreographer.

Como invalidate() difere de postInvalidate()?

invalidate() funciona apenas na thread de UI e atualiza a flag dirty imediatamente. postInvalidate() envia uma solicitação através de Handler para a thread de UI e pode ser chamado de qualquer thread em segundo plano. Se você está na thread de UI — use invalidate() para latência mínima.

setText() em TextView chama automaticamente invalidate()?

Sim, internamente o método setText() do TextView chama invalidate() após atualizar o texto. Se o texto alterar as dimensões da view, requestLayout() também é chamado. Os desenvolvedores não precisam chamar invalidate() manualmente ao trabalhar com widgets padrão.

Como invalidate() afeta o desempenho a 60 FPS?

Cada chamada a invalidate() agenda um redesenho no próximo Vsync (a cada 16 ms). Se onDraw() levar mais de 16 ms, ocorrem quedas de quadros. Otimize onDraw() — armazene Bitmaps em cache, evite alocações e use aceleração de hardware para renderização por GPU.

É necessário chamar invalidate() após alterar propriedades de Paint?

Sim, após alterar propriedades de Paint (cor, espessura, estilo), você deve chamar invalidate(), porque a View não rastreia automaticamente as alterações em objetos Paint. O sistema não sabe que o Paint mudou e não chamará onDraw() sem uma solicitação explícita.

Resumo

  • invalidate() — o mecanismo principal para solicitar redesenho de View no Android, funciona de forma assíncrona através da flag dirty
  • postInvalidate() — versão thread-safe para chamar de threads em segundo plano, usa Handler
  • invalidate(Rect) — redesenho parcial apenas da área especificada, crítico para desempenho com alterações direcionadas
  • requestLayout() — desencadeia um ciclo completo measure + layout + draw, significativamente mais pesado que invalidate()
  • Choreographer — serviço do sistema para sincronização com Vsync, recomendado para animações com invalidate()
  • Hardware Acceleration — aceleração por GPU disponível desde a API 14, acelera o processamento de invalidate() para Canvas API
  • GPU Profile Rendering — ferramenta de perfil para medir o tempo de renderização e identificar métodos onDraw() lentos

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também