← Назад к вопросам

Гарантирует ли метод invalidate перерисовку View?

2.0 Middle🔥 61 комментариев
#Android компоненты#UI и вёрстка

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ответ на вопрос о методе invalidate()

Метод invalidate() НЕ гарантирует полную перерисовку View напрямую. Это важный нюанс, который часто путают разработчики.

Что реально делает invalidate()

invalidate() просто помечает View как «грязную» и запрашивает перерисовку. Вот что происходит:

// View будет перерисована в следующем цикле отрисовки
view.invalidate() // Вызов из основного потока

// Если вызвать из фонового потока — исключение
Thread { view.invalidate() }.start() // IllegalArgumentException!

Отличие invalidate() от requestLayout()

  • invalidate() → перерисовка (onDraw), без изменения размеров
  • requestLayout() → пересчёт размеров и позиций, затем перерисовка
view.invalidate()        // Только onDraw
view.requestLayout()     // onMeasure → onLayout → onDraw
view.postInvalidate()    // invalidate() из другого потока

Гарантии invalidate()

Что гарантирует:

  • View будет отмечена для перерисовки
  • onDraw() будет вызван в следующий цикл отрисовки
  • Работает ТОЛЬКО из UI потока

Что НЕ гарантирует:

  • Мгновенную перерисовку (асинхронно)
  • Если View невидима или не добавлена на layout
  • Если View находится вне видимой области экрана (система может пропустить)

Практические примеры

class CustomView(context: Context) : View(context) {
    private var color = Color.RED
    
    fun changeColor() {
        color = Color.BLUE
        invalidate() // Плани́рует onDraw на следующий цикл
    }
    
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawColor(color)
    }
}

// Использование
val view = CustomView(this)
view.changeColor() // Не перерисуется мгновенно!

// Для гарантированной перерисовки из фонового потока
Thread {
    view.postInvalidate() // Безопасно
}.start()

Когда invalidate() не сработает

  1. Вызов из фонового потока без postInvalidate()
  2. View находится в GONE состоянии
  3. View ещё не добавлена на layout (getParent() == null)
  4. Canvas отключен (например, на минимизированном приложении)

Оптимизация

Для часто меняющегося контента используй invalidate(Rect):

// Перерисовать только часть View (экономия ресурсов)
val dirtyRect = Rect(0, 0, 100, 100)
view.invalidate(dirtyRect)

Итог

invalidate() **гарантирует запрос на перерисовку**, но не гарантирует саму перерисовку если View недоступна для рисования. Это планировщик, а не команда с немедленным эффектом.
Гарантирует ли метод invalidate перерисовку View? | PrepBro