invalidate() — Cos'è, meccanismo di ridisegno e invalidate(Rect)

Autore: IT Sectr Pubblicato: 2026-07-20 Tempo di lettura: 7 min

invalidate() è un metodo della classe View in Android che marca una vista come bisognosa di essere ridisegnata. La chiamata a invalidate() provoca un ridisegno della vista nel prossimo ciclo di aggiornamento dello schermo, rendendolo il meccanismo principale per aggiornare lo stato visivo dei componenti personalizzati. Secondo la documentazione Android Developers (2025), invalidate() è utilizzato nel 90% delle View personalizzate per sincronizzare le modifiche dei dati con la visualizzazione sullo schermo. Il metodo funziona in modo asincrono — imposta solo il flag dirty e restituisce immediatamente il controllo.

Punti chiave

  • invalidate() — una richiesta asincrona per ridisegnare View in Android, funziona tramite il meccanismo del flag dirty
  • postInvalidate() — versione di invalidate() per chiamata da thread in background, thread-safe
  • invalidate(Rect) — ridisegno parziale solo dell'area specificata per ottimizzazione delle prestazioni
  • onDraw() — il metodo chiamato dal sistema dopo invalidate(), simile a draw(_:) in iOS
  • invalidate() vs requestLayout() — invalidate() ridisegna il contenuto, requestLayout() ricalcola la geometria

Cos'è invalidate() in Android

invalidate() è un metodo della classe android.view.View che comunica al sistema Android che la rappresentazione visiva di una vista è obsoleta. Dopo aver chiamato il metodo, il sistema marca la vista come dirty e pianifica il suo ridisegno nel prossimo ciclo di aggiornamento dello schermo (solitamente 16 ms per 60 FPS).

Il metodo invalidate() si presenta in varie forme: senza parametri (ridisegno completo), con un parametro Rect (parziale) e con parametri ltrb (left, top, right, bottom). Tutte le versioni funzionano in modo asincrono e devono essere chiamate dal thread UI. Per le chiamate da thread in background esiste postInvalidate().

Come funziona il ridisegno tramite invalidate()

Il meccanismo di ridisegno in Android si basa su ViewRootImpl — un componente interno che collega la gerarchia delle viste alla superficie di disegno. Quando viene chiamato invalidate(), ViewRootImpl marca l'area della vista come dirty e invia una richiesta di ridisegno tramite Choreographer — un servizio di sistema che sincronizza il disegno con la frequenza di aggiornamento dello schermo.

Il ciclo di ridisegno

Choreographer riceve un segnale da Vsync e avvia un triplice passaggio: measure, layout, draw. Tuttavia, invalidate() interessa solo la fase draw — le fasi measure e layout non vengono eseguite a meno che non sia stato chiamato requestLayout(). Questa è una differenza chiave: invalidate() è più leggero di requestLayout() perché non ricalcola la 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() // Richiesta di ridisegno
    }

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

        // Disegnando linea del grafico
        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)
    }
}

In questo esempio, una View personalizzata per disegnare un grafico chiama invalidate() quando i dati vengono aggiornati. Il sistema ridisegna solo questa View senza influenzare gli altri elementi nella gerarchia. onDraw() riceve un Canvas per disegnare linee tramite Path.

invalidate() vs postInvalidate()

La differenza principale tra invalidate() e postInvalidate() risiede nella sicurezza dei thread. invalidate() deve essere chiamato solo dal thread UI (thread principale). postInvalidate() può essere chiamato da qualsiasi thread — invia una richiesta di ridisegno al thread UI tramite Handler.

Caratteristicainvalidate()postInvalidate()
Thread di chiamataThread UI (thread principale)Qualsiasi thread
MeccanismoAggiornamento diretto del flag dirtyTramite Handler.post() al thread UI
LatenzaMinima, nel ciclo correnteFino al prossimo ciclo del thread UI
PrestazioniAlteLeggero overhead di Handler
RaccomandazioneSempre invalidate() per il thread UISolo per thread in background

In pratica, postInvalidate() viene utilizzato in scenari di caricamento dati di rete, elaborazione di risultati di sensori o calcoli in background. Se ti trovi nel thread UI — usa sempre invalidate() per una latenza minima.

kotlin
    // Chiamato dal thread UI
view.invalidate()

    // Chiamato dal thread in background
Thread {
    // Calcoli pesanti
    val result = performHeavyCalculation()
    runOnUiThread {
        updateUi(result)
    }
}.start()

Ridisegno parziale tramite invalidate(Rect)

invalidate(Rect) e invalidate(int l, int t, int r, int b) permettono di limitare l'area di ridisegno. Questo è fondamentale per le prestazioni: quando cambia solo una parte di una View (ad esempio, movimento del cursore, cambio indicatore), non è necessario ridisegnare l'intera vista.

Il sistema passa il rettangolo dirty specificato a onDraw() tramite canvas.clipBounds. All'interno di onDraw(), è possibile verificare clipBounds e disegnare solo all'interno di quell'area, sebbene Android Canvas ritagli automaticamente il disegno al di fuori del rettangolo dirty.

kotlin
    // Aggiornamento parziale: solo area cursore
private val cursorRect = Rect()

fun moveCursorTo(newX: Int, newY: Int) {
    // Invalidare posizione vecchia
    invalidate(cursorRect)

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

    // Invalidare nuova posizione
    invalidate(cursorRect)
}

Senza ridisegno parziale, ogni movimento del cursore ridisegnerebbe l'intera View, che per un grafico grande significa ridisegnare migliaia di pixel invece di poche decine. invalidate(Rect) è una tecnica essenziale per editor, canvas di disegno e componenti animati.

invalidate() vs requestLayout(): qual è la differenza

Un errore comune è chiamare requestLayout() dove basterebbe invalidate(), e viceversa. La differenza è fondamentale: invalidate() interessa solo la fase draw, mentre requestLayout() attiva un ciclo completo measure → layout → draw.

Aspettoinvalidate()requestLayout()
Fasi del cicloSolo drawmeasure + layout + draw
Quando usarloSolo il rendering cambia (colore, testo, grafica)La dimensione o la posizione della vista cambia
PrestazioniLeggero — solo ridisegnoPesante — ricalcola la gerarchia
Impatto sulla gerarchiaSolo la vista correntePuò influenzare i contenitori padre

Se modifichi il testo in un TextView, invalidate() è sufficiente poiché la dimensione della vista non cambia. Se il testo può andare a capo e aumentare l'altezza, è necessario requestLayout(). Android Lint aiuta a tracciare questi errori attraverso regole di prestazione.

Ottimizzazione delle prestazioni di invalidate()

Le chiamate eccessive a invalidate() sono una delle principali cause di scarse prestazioni delle View personalizzate in Android. Esaminiamo le tecniche di ottimizzazione.

Minimizza la frequenza delle chiamate

Se i dati vengono aggiornati ad alta frequenza (sensori, animazioni, video), non chiamare invalidate() ad ogni modifica. Usa ValueAnimator o Choreographer.FrameCallback per sincronizzarti con la frequenza di aggiornamento dello schermo. Questo garantisce che invalidate() non venga chiamato più di una volta per fotogramma.

Usa l'accelerazione hardware

Dall'API 14, Android supporta l'accelerazione hardware tramite GPU. Se la tua View personalizzata utilizza solo Canvas API (drawRect, drawCircle, drawPath), l'accelerazione funziona in modo trasparente. Per le operazioni compatibili con DisplayList, invalidate() viene elaborato significativamente più velocemente.

kotlin
// Usando Choreographer per sincronizzazione Vsync
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
    updateAnimation(frameTimeNanos)
    invalidate()
    Choreographer.getInstance().postFrameCallback(this)
}

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

Usa invalidate(Rect) per aggiornamenti mirati, evita di chiamare invalidate() da onDraw() (ciclo infinito) e profilare sempre tramite GPU Profile Rendering su un dispositivo. Questo mostrerà il tempo esatto di rendering di ogni fotogramma e aiuterà a identificare le aree problematiche.

Domande frequenti

Si può chiamare invalidate() da onDraw()?

No, chiamare invalidate() all'interno di onDraw() crea un ciclo infinito di ridisegno: onDraw() chiama invalidate(), che a sua volta attiva onDraw(). Questo porta al 100% di utilizzo della CPU e caduta di fotogrammi. Usa animazioni tramite ValueAnimator o Choreographer.

In cosa differisce invalidate() da postInvalidate()?

invalidate() funziona solo nel thread UI e aggiorna il flag dirty immediatamente. postInvalidate() invia una richiesta tramite Handler al thread UI e può essere chiamato da qualsiasi thread in background. Se sei nel thread UI — usa invalidate() per una latenza minima.

setText() in TextView chiama automaticamente invalidate()?

Sì, internamente il metodo setText() di TextView chiama invalidate() dopo aver aggiornato il testo. Se il testo modifica le dimensioni della vista, viene chiamato anche requestLayout(). Gli sviluppatori non devono chiamare manualmente invalidate() quando lavorano con widget standard.

Come influisce invalidate() sulle prestazioni a 60 FPS?

Ogni chiamata a invalidate() pianifica un ridisegno nel prossimo Vsync (ogni 16 ms). Se onDraw() richiede più di 16 ms, si verificano cadute di fotogrammi. Ottimizza onDraw() — memorizza nella cache i Bitmap, evita allocazioni e usa l'accelerazione hardware per il rendering GPU.

È necessario chiamare invalidate() dopo aver modificato le proprietà di Paint?

Sì, dopo aver modificato le proprietà di Paint (colore, spessore, stile), devi chiamare invalidate(), perché la View non tiene traccia automaticamente delle modifiche agli oggetti Paint. Il sistema non sa che Paint è cambiato e non chiamerà onDraw() senza una richiesta esplicita.

Riepilogo

  • invalidate() — il meccanismo principale per richiedere il ridisegno di View in Android, funziona in modo asincrono tramite il flag dirty
  • postInvalidate() — versione thread-safe per chiamate da thread in background, usa Handler
  • invalidate(Rect) — ridisegno parziale solo dell'area specificata, fondamentale per le prestazioni con modifiche mirate
  • requestLayout() — attiva un ciclo completo measure + layout + draw, significativamente più pesante di invalidate()
  • Choreographer — servizio di sistema per la sincronizzazione Vsync, raccomandato per animazioni con invalidate()
  • Hardware Acceleration — accelerazione GPU disponibile dall'API 14, velocizza l'elaborazione di invalidate() per Canvas API
  • GPU Profile Rendering — strumento di profilazione per misurare il tempo di rendering e identificare metodi onDraw() lenti

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche