invalidate() — шта је то, механизам прецртавања и invalidate(Rect)

Аутор: IT Sectr Објављено: 2026-07-20 Време читања: 7 мин

invalidate() — је метода класе View у Android-у која означава приказ као да захтева поновно цртање. Позив invalidate() доводи до прецртавања приказа у најближем циклусу ажурирања екрана, што га чини главним механизмом за ажурирање визуелног стања прилагођених компонената. Према Android Developers Documentation (2025), invalidate() се користи у 90% прилагођених View-ова за синхронизацију промена података са приказом на екрану. Метода ради асинхроно — само поставља dirty заставицу и одмах враћа контролу.

Главно

  • invalidate() — асинхрони захтев за прецртавање View-а у Android-у, ради кроз dirty flag механизам
  • postInvalidate() — верзија invalidate()-а за позивање из позадинске нити, безбедна за нити
  • invalidate(Rect) — делимично прецртавање само наведене области за оптимизацију перформанси
  • onDraw() — метода коју систем позива након invalidate()-а, аналогна draw(_:) у iOS-у
  • invalidate() vs requestLayout() — invalidate() прецртава садржај, requestLayout() поново израчунава геометрију

Шта је invalidate() у Android-у

invalidate() — је метода класе android.view.View која обавештава Android систем да је визуелни приказ приказа застарео. Након позива методе, систем означава приказ као dirty и планира његово прецртавање у најближем циклусу ажурирања екрана (обично 16 ms за 60 FPS).

Метода invalidate() прима различите облике: без параметара (потпуно прецртавање), са параметром Rect (делимично) и са параметрима ltrb (left, top, right, bottom). Све верзије раде асинхроно и могу се позивати из UI нити. За позивање из позадинских нити постоји postInvalidate().

Како функционише прецртавање кроз invalidate()

Механизам прецртавања у Android-у се заснива на ViewRootImpl — унутрашњој компоненти која повезује View Hierarchy са Surface-ом за цртање. Када се позове invalidate(), ViewRootImpl означава област приказа као dirty и шаље захтев за прецртавање кроз Choreographer — системски сервис који синхронизује цртање са учесталошћу ажурирања екрана.

Циклус прецртавања

Choreographer прима сигнал од Vsync-а и покреће троструки пролаз: measure, layout, draw. Међутим, invalidate() утиче само на фазу draw — фазе measure и layout се не извршавају ако није позван requestLayout(). Ово је кључна разлика: invalidate() је јефтинији од requestLayout()-а јер не прерачунава геометрију.

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() // Захтев за прецртавање
    }

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

        // Цртање линије графикона
        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)
    }
}

У овом примеру, прилагођени View за цртање графикона позива invalidate() при ажурирању података. Систем прецртава само овај View, не утичући на остале елементе хијерархије. onDraw() добија Canvas за цртање линија кроз Path.

invalidate() vs postInvalidate()

Главна разлика између invalidate()-а и postInvalidate()-а је у безбедности нити. invalidate() се сме позивати само из UI нити (главне нити). postInvalidate() се може позвати из било које нити — кроз Handler шаље захтев за прецртавање у UI нит.

Карактеристикаinvalidate()postInvalidate()
Нит позиваUI нит (главна нит)Било која нит
МеханизамДиректно ажурирање dirty заставицеКроз Handler.post() ка UI нити
КасњењеМинимално, у тренутном циклусуДо следећег циклуса UI нити
ПерформансеВисокеМали overhead на Handler-у
ПрепорукаЗа UI нит увек invalidate()Само за позадинске нити

У пракси, postInvalidate() се користи у сценаријима учитавања података из мреже, обраде резултата сензора или позадинских израчунавања. Ако се налазите у UI нити — увек користите invalidate() за минимално кашњење.

kotlin
    // Позвано из UI нити
view.invalidate()

    // Позвано из позадинске нити
Thread {
    // Тешка израчунавања
    val result = performHeavyCalculation()
    runOnUiThread {
        updateUi(result)
    }
}.start()

Делимично прецртавање кроз invalidate(Rect)

invalidate(Rect) и invalidate(int l, int t, int r, int b) омогућавају ограничавање области прецртавања. Ово је критично за перформансе: при ажурирању само дела View-а (нпр. померање курсора, промена индикатора) нема смисла прецртавати цео приказ.

Систем прослеђује наведени dirty правоугаоник у onDraw() кроз canvas.clipBounds. Унутар onDraw()-а може се проверити clipBounds и цртати само у границама ове области, иако Android Canvas аутоматски ограничава цртање изван dirty правоугаоника.

kotlin
    // Делимично ажурирање: само област курсора
private val cursorRect = Rect()

fun moveCursorTo(newX: Int, newY: Int) {
    // Поништи стару позицију
    invalidate(cursorRect)

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

    // Поништи нову позицију
    invalidate(cursorRect)
}

Без делимичног прецртавања, сваки покрет курсора би прецртавао цео View, што за велики графикон значи прецртавање хиљада пиксела уместо неколико десетина. invalidate(Rect) — обавезна техника за едиторе, платна за цртање и анимиране компоненте.

invalidate() vs requestLayout(): у чему је разлика

Једна од честих грешака је позивање requestLayout()-а тамо где је довољан invalidate(), и обрнуто. Разлика је фундаментална: invalidate() утиче само на фазу draw, док requestLayout() покреће потпуни циклус measure → layout → draw.

Аспектinvalidate()requestLayout()
Фазе циклусаСамо drawmeasure + layout + draw
Када користитиМења се само цртање (боја, текст, графика)Мења се величина или положај приказа
ПерформансеЛагано — само прецртавањеТешко — прерачунавање хијерархије
Утицај на хијерархијуСамо тренутни приказМоже утицати на родитељске контејнере

Ако мењате текст у TextView-у — довољан је invalidate(), јер се величина приказа не мења. Ако текст може да пређе у нови ред и повећа висину — потребан је requestLayout(). Android Lint помаже у праћењу оваквих грешака кроз правила перформанси.

Оптимизација перформанси invalidate()-а

Прекомерни позиви invalidate()-а — један од главних узрока ниских перформанси прилагођених View-ова у Android-у. Размотримо технике оптимизације.

Минимизирајте учесталост позива

Ако се подаци ажурирају високом учесталошћу (сензори, анимација, видео), не позивајте invalidate() при свакој промени. Користите ValueAnimator или Choreographer.FrameCallback за синхронизацију са учесталошћу ажурирања екрана. Ово гарантује да се invalidate() позива не више од једном по кадру.

Користите Hardware Acceleration

Од API 14, Android подржава хардверско убрзање кроз GPU. Ако ваш прилагођени View користи само Canvas API (drawRect, drawCircle, drawPath), убрзање ради транспарентно. За операције компатибилне са DisplayList-ом, invalidate() се обрађује значајно брже.

kotlin
// Коришћење Choreographer-а за Vsync синхронизацију
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
    updateAnimation(frameTimeNanos)
    invalidate()
    Choreographer.getInstance().postFrameCallback(this)
}

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

Користите invalidate(Rect) за тачкаста ажурирања, избегавајте позивање invalidate()-а из onDraw()-а (бесконачна петља) и увек профилишите кроз GPU Profile Rendering на уређају. Ово ће показати тачно време цртања сваког кадра и помоћи у идентификацији проблематичних места.

Често постављана питања

Може ли се invalidate() позвати из onDraw()-а?

Не, позив invalidate()-а унутар onDraw()-а ствара бесконачни циклус прецртавања: onDraw() позива invalidate(), који поново покреће onDraw(). Ово доводи до 100% оптерећења CPU-а и пада броја кадрова. Користите анимације кроз ValueAnimator или Choreographer.

По чему се invalidate() разликује од postInvalidate()-а?

invalidate() ради само у UI нити и ажурира dirty заставицу одмах. postInvalidate() шаље захтев кроз Handler у UI нит и може се позвати из било које позадинске нити. Ако сте у UI нити — користите invalidate() за минимално кашњење.

Да ли setText() у TextView-у аутоматски позива invalidate()?

Да, унутар TextView-а метода setText() позива invalidate() након ажурирања текста. Ако је текст променио димензије приказа, додатно се позива requestLayout(). Програмер не мора ручно да позива invalidate() при раду са стандардним виџетима.

Како invalidate() утиче на перформансе при 60 FPS?

Сваки позив invalidate()-а планира прецртавање у следећем Vsync-у (сваких 16 ms). Ако onDraw() траје дуже од 16 ms, долази до пада кадрова. Оптимизујте onDraw() — кеширајте Bitmap, избегавајте алокације и користите Hardware Acceleration за GPU цртање.

Да ли треба позвати invalidate() након промене својстава Paint-а?

Да, након промене својстава Paint-а (боја, дебљина, стил) потребно је позвати invalidate(), јер View не прати промене Paint објеката аутоматски. Систем не зна да се Paint променио и неће позвати onDraw() без експлицитног захтева.

Резиме

  • invalidate() — главни механизам захтева за прецртавање View-а у Android-у, ради асинхроно кроз dirty flag
  • postInvalidate() — верзија безбедна за нити за позивање из позадинских нити, користи Handler
  • invalidate(Rect) — делимично прецртавање само наведене области, критично за перформансе при тачкастим променама
  • requestLayout() — покреће потпуни циклус measure + layout + draw, значајно тежи од invalidate()-а
  • Choreographer — системски сервис за синхронизацију са Vsync-ом, препоручује се за анимације са invalidate()-ом
  • Hardware Acceleration — GPU убрзање доступно од API 14, убрзава обраду invalidate()-а за Canvas API
  • GPU Profile Rendering — алат за профилисање за мерење времена цртања и идентификацију спорих onDraw()-а

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође