← Назад к вопросам
Гарантирует ли метод 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() не сработает
- Вызов из фонового потока без postInvalidate()
- View находится в GONE состоянии
- View ещё не добавлена на layout (getParent() == null)
- Canvas отключен (например, на минимизированном приложении)
Оптимизация
Для часто меняющегося контента используй invalidate(Rect):
// Перерисовать только часть View (экономия ресурсов)
val dirtyRect = Rect(0, 0, 100, 100)
view.invalidate(dirtyRect)
Итог
invalidate() **гарантирует запрос на перерисовку**, но не гарантирует саму перерисовку если View недоступна для рисования. Это планировщик, а не команда с немедленным эффектом.