invalidate() — co to je, mechanismus překreslení a invalidate(Rect)

Autor: IT Sectr Publikováno: 2026-07-20 Doba čtení: 7 min

invalidate() — je metoda třídy View v Androidu, která označuje zobrazení jako vyžadující překreslení. Volání invalidate() vede k překreslení zobrazení v nejbližším cyklu aktualizace obrazovky, což z něj činí hlavní mechanismus aktualizace vizuálního stavu vlastních komponent. Podle Android Developers Documentation (2025) se invalidate() používá v 90% vlastních View k synchronizaci změn dat se zobrazením na obrazovce. Metoda pracuje asynchronně — pouze nastaví příznak dirty a okamžitě vrátí řízení.

Hlavní body

  • invalidate() — asynchronní požadavek na překreslení View v Androidu, pracuje přes mechanismus dirty flag
  • postInvalidate() — verze invalidate() pro volání z vlákna na pozadí, bezpečná pro vlákna
  • invalidate(Rect) — částečné překreslení pouze zadané oblasti pro optimalizaci výkonu
  • onDraw() — metoda volaná systémem po invalidate(), analogická draw(_:) v iOS
  • invalidate() vs requestLayout() — invalidate() překresluje obsah, requestLayout() přepočítává geometrii

Co je invalidate() v Androidu

invalidate() — je metoda třídy android.view.View, která informuje systém Android, že vizuální reprezentace zobrazení je zastaralá. Po volání metody systém označí zobrazení jako dirty a naplánuje jeho překreslení v nejbližším cyklu aktualizace obrazovky (obvykle 16 ms pro 60 FPS).

Metoda invalidate() přijímá různé formy: bez parametrů (úplné překreslení), s parametrem Rect (částečné) a s parametry ltrb (left, top, right, bottom). Všechny verze pracují asynchronně a mohou být volány z UI vlákna. Pro volání z vláken na pozadí existuje postInvalidate().

Jak funguje překreslení přes invalidate()

Mechanismus překreslení v Androidu je založen na ViewRootImpl — interní komponentě, která spojuje View Hierarchy s Surface pro kreslení. Když je zavoláno invalidate(), ViewRootImpl označí oblast zobrazení jako dirty a odešle požadavek na překreslení přes Choreographer — systémovou službu synchronizující kreslení s frekvencí aktualizace obrazovky.

Cyklus překreslení

Choreographer obdrží signál z Vsync a spustí trojitý průchod: measure, layout, draw. Nicméně invalidate() ovlivňuje pouze fázi draw — fáze measure a layout se neprovádějí, pokud nebylo zavoláno requestLayout(). To je klíčový rozdíl: invalidate() je levnější než requestLayout(), protože nepřepočítává geometrii.

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() // Požadavek na překreslení
    }

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

        // Kreslení čáry grafu
        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)
    }
}

V tomto příkladu vlastní View pro kreslení grafu volá invalidate() při aktualizaci dat. Systém překreslí pouze toto View, aniž by ovlivnil ostatní prvky hierarchie. onDraw() obdrží Canvas pro kreslení čar přes Path.

invalidate() vs postInvalidate()

Hlavní rozdíl mezi invalidate() a postInvalidate() je v bezpečnosti vláken. invalidate() smí být voláno pouze z UI vlákna (hlavního vlákna). postInvalidate() lze volat z libovolného vlákna — přes Handler odesílá požadavek na překreslení do UI vlákna.

Vlastnostinvalidate()postInvalidate()
Vlákno voláníUI vlákno (hlavní vlákno)Libovolné vlákno
MechanismusPřímá aktualizace dirty flagPřes Handler.post() do UI vlákna
LatenceMinimální, v aktuálním cykluDo příštího cyklu UI vlákna
VýkonVysokýMalá režie na Handleru
DoporučeníPro UI vlákno vždy invalidate()Pouze pro vlákna na pozadí

V praxi se postInvalidate() používá ve scénářích načítání dat ze sítě, zpracování výsledků senzorů nebo výpočtů na pozadí. Pokud jste v UI vlákně — vždy používejte invalidate() pro minimální latenci.

kotlin
    // Voláno z UI vlákna
view.invalidate()

    // Voláno z vlákna na pozadí
Thread {
    // Těžké výpočty
    val result = performHeavyCalculation()
    runOnUiThread {
        updateUi(result)
    }
}.start()

Částečné překreslení přes invalidate(Rect)

invalidate(Rect) a invalidate(int l, int t, int r, int b) umožňují omezit oblast překreslení. To je kritické pro výkon: při aktualizaci pouze části View (např. pohyb kurzoru, změna indikátoru) nemá smysl překreslovat celé zobrazení.

Systém předá zadaný dirty obdélník do onDraw() přes canvas.clipBounds. Uvnitř onDraw() lze zkontrolovat clipBounds a kreslit pouze v mezích této oblasti, ačkoli Android Canvas automaticky ořezává kreslení mimo dirty obdélník.

kotlin
    // Částečná aktualizace: pouze oblast kurzoru
private val cursorRect = Rect()

fun moveCursorTo(newX: Int, newY: Int) {
    // Zneplatnit starou pozici
    invalidate(cursorRect)

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

    // Zneplatnit novou pozici
    invalidate(cursorRect)
}

Bez částečného překreslení by každý pohyb kurzoru překresloval celé View, což pro velký graf znamená překreslení tisíců pixelů místo několika desítek. invalidate(Rect) — povinná technika pro editory, kreslicí plátna a animované komponenty.

invalidate() vs requestLayout(): jaký je rozdíl

Jednou z častých chyb je volání requestLayout() tam, kde stačí invalidate(), a naopak. Rozdíl je zásadní: invalidate() ovlivňuje pouze fázi draw, zatímco requestLayout() spouští celý cyklus measure → layout → draw.

Aspektinvalidate()requestLayout()
Fáze cykluPouze drawmeasure + layout + draw
Kdy použítMění se pouze kreslení (barva, text, grafika)Mění se velikost nebo pozice zobrazení
VýkonLehké — pouze překresleníTěžké — přepočet hierarchie
Dopad na hierarchiiPouze aktuální zobrazeníMůže ovlivnit nadřazené kontejnery

Pokud měníte text v TextView — stačí invalidate(), protože velikost zobrazení se nemění. Pokud se text může přesunout na nový řádek a zvýšit výšku — je potřeba requestLayout(). Android Lint pomáhá sledovat takové chyby prostřednictvím pravidel výkonu.

Optimalizace výkonu invalidate()

Nadměrná volání invalidate() — jeden z hlavních důvodů nízkého výkonu vlastních View v Androidu. Podívejme se na techniky optimalizace.

Minimalizujte frekvenci volání

Pokud se data aktualizují s vysokou frekvencí (senzory, animace, video), nevolejte invalidate() při každé změně. Používejte ValueAnimator nebo Choreographer.FrameCallback pro synchronizaci s frekvencí aktualizace obrazovky. To zaručuje, že invalidate() není voláno více než jednou za snímek.

Používejte Hardware Acceleration

Od API 14 Android podporuje hardwarovou akceleraci přes GPU. Pokud vaše vlastní View používá pouze Canvas API (drawRect, drawCircle, drawPath), akcelerace pracuje transparentně. Pro operace kompatibilní s DisplayList je invalidate() zpracováváno výrazně rychleji.

kotlin
// Použití Choreographer pro synchronizaci Vsync
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
    updateAnimation(frameTimeNanos)
    invalidate()
    Choreographer.getInstance().postFrameCallback(this)
}

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

Používejte invalidate(Rect) pro bodové aktualizace, vyhněte se volání invalidate() z onDraw() (nekonečná smyčka) a vždy profilujte přes GPU Profile Rendering na zařízení. To ukáže přesný čas kreslení každého snímku a pomůže identifikovat problematická místa.

Často kladené otázky

Lze volat invalidate() z onDraw()?

Ne, volání invalidate() uvnitř onDraw() vytváří nekonečnou smyčku překreslování: onDraw() volá invalidate(), který znovu spouští onDraw(). To vede k 100% zatížení CPU a ztrátě snímků. Používejte animace přes ValueAnimator nebo Choreographer.

Čím se liší invalidate() od postInvalidate()?

invalidate() pracuje pouze v UI vlákně a aktualizuje dirty flag okamžitě. postInvalidate() odesílá požadavek přes Handler do UI vlákna a může být voláno z libovolného vlákna na pozadí. Pokud jste v UI vlákně — používejte invalidate() pro minimální latenci.

Volá setText() v TextView automaticky invalidate()?

Ano, uvnitř TextView metoda setText() volá invalidate() po aktualizaci textu. Pokud text změnil rozměry zobrazení, dodatečně je voláno requestLayout(). Vývojář nemusí ručně volat invalidate() při práci se standardními widgety.

Jak invalidate() ovlivňuje výkon při 60 FPS?

Každé volání invalidate() plánuje překreslení v příštím Vsync (každých 16 ms). Pokud onDraw() trvá déle než 16 ms, dochází ke ztrátě snímků. Optimalizujte onDraw() — kešujte Bitmap, vyhněte se alokacím a používejte Hardware Acceleration pro GPU kreslení.

Je třeba volat invalidate() po změně vlastností Paint?

Ano, po změně vlastností Paint (barva, tloušťka, styl) je třeba volat invalidate(), protože View nesleduje změny objektů Paint automaticky. Systém neví, že se Paint změnil, a bez explicitního požadavku nezavolá onDraw().

Shrnutí

  • invalidate() — hlavní mechanismus požadavku na překreslení View v Androidu, pracuje asynchronně přes dirty flag
  • postInvalidate() — bezpečná verze pro vlákna pro volání z vláken na pozadí, používá Handler
  • invalidate(Rect) — částečné překreslení pouze zadané oblasti, kritické pro výkon při bodových změnách
  • requestLayout() — spouští celý cyklus measure + layout + draw, výrazně těžší než invalidate()
  • Choreographer — systémová služba pro synchronizaci s Vsync, doporučená pro animace s invalidate()
  • Hardware Acceleration — GPU akcelerace dostupná od API 14, urychluje zpracování invalidate() pro Canvas API
  • GPU Profile Rendering — nástroj profilování pro měření času kreslení a identifikaci pomalých onDraw()

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také