invalidate() — Android-dagi View sinfining metodi bo'lib, ko'rinishni qayta chizish talab qiladigan deb belgilaydi. invalidate() chaqiruvi ekran yangilanish siklining eng yaqin vaqtida ko'rinishni qayta chizishga olib keladi va bu uni maxsus komponentlarning vizual holatini yangilashning asosiy mexanizmiga aylantiradi. Android Developers Documentation (2025) ma'lumotlariga ko'ra, invalidate() ma'lumotlar o'zgarishlarini ekranda ko'rsatish bilan sinxronlash uchun 90% maxsus View-larda ishlatiladi. Metod asinxron ishlaydi — u faqat dirty flagini o'rnatadi va darhol boshqaruvni qaytaradi.
Asosiy fikrlar
invalidate() — android.view.View sinfining metodi bo'lib, Android tizimiga ko'rinishning vizual tasviri eskirganligini bildiradi. Metod chaqirilgandan so'ng, tizim ko'rinishni dirty deb belgilaydi va uni ekran yangilanish siklining eng yaqin vaqtida qayta chizishni rejalashtiradi (odatda 60 FPS uchun 16 ms).
invalidate() metodi turli shakllarni qabul qiladi: parametrsiz (to'liq qayta chizish), Rect parametri bilan (qisman) va ltrb parametrlari bilan (left, top, right, bottom). Barcha versiyalar asinxron ishlaydi va UI thread-dan chaqirilishi mumkin. Fon thread-lardan chaqirish uchun postInvalidate() mavjud.
Android-da qayta chizish mexanizmi ViewRootImpl ga asoslangan — View Hierarchy-ni chizish uchun Surface bilan bog'laydigan ichki komponent. invalidate() chaqirilganda, ViewRootImpl ko'rinish hududini dirty deb belgilaydi va Choreographer — chizishni ekran yangilanish chastotasi bilan sinxronlaydigan tizim xizmati orqali qayta chizish so'rovini yuboradi.
Choreographer Vsync dan signal oladi va uchlik o'tishni ishga tushiradi: measure, layout, draw. Biroq invalidate() faqat draw fazasiga ta'sir qiladi — measure va layout fazalari requestLayout() chaqirilmagan bo'lsa, bajarilmaydi. Bu asosiy farq: invalidate() requestLayout() dan yengilroq, chunki geometriyani qayta hisoblamaydi.
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() // Qayta chizish so'rovi
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
paint.color = Color.BLUE
paint.strokeWidth = 4f
paint.style = Paint.Style.STROKE
// Grafik chizig'ini chizish
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)
}
}
Ushbu misolda, grafik chizish uchun maxsus View ma'lumot yangilanganda invalidate() chaqiradi. Tizim faqat shu View-ni qayta chizadi, iyerarxiyaning qolgan elementlariga ta'sir qilmaydi. onDraw() Path orqali chiziqlar chizish uchun Canvas oladi.
invalidate() va postInvalidate() o'rtasidagi asosiy farq thread xavfsizligidadir. invalidate() faqat UI thread-dan (main thread) chaqirilishi kerak. postInvalidate() istalgan thread-dan chaqirilishi mumkin — Handler orqali qayta chizish so'rovini UI thread-ga yuboradi.
| Xususiyat | invalidate() | postInvalidate() |
|---|---|---|
| Chaqirish thread-i | UI thread (asosiy thread) | Istalgan thread |
| Mexanizm | Dirty flag-ni to'g'ridan-to'g'ri yangilash | Handler.post() orqali UI thread-ga |
| Kechikish | Minimal, joriy siklda | Keyingi UI thread sikligacha |
| Ishlash | Yuqori | Handlerda kichik qo'shimcha yuk |
| Tavsiya | UI thread uchun har doim invalidate() | Faqat fon thread-lari uchun |
Amalda, postInvalidate() tarmoqdan ma'lumot yuklash, sensor natijalarini qayta ishlash yoki fon hisoblash stsenariylarida ishlatiladi. UI thread-da bo'lsangiz — minimal kechikish uchun har doim invalidate() dan foydalaning.
// UI thread-dan chaqirildi
view.invalidate()
// Fon thread-dan chaqirildi
Thread {
// Og'ir hisoblar
val result = performHeavyCalculation()
runOnUiThread {
updateUi(result)
}
}.start()
invalidate(Rect) va invalidate(int l, int t, int r, int b) qayta chizish hududini cheklash imkonini beradi. Bu ishlash uchun juda muhim: View-ning faqat bir qismi yangilanganda (masalan, kursor harakati, indikator o'zgarishi) butun ko'rinishni qayta chizishning ma'nosi yo'q.
Tizim belgilangan dirty to'rtburchakni onDraw() ga canvas.clipBounds orqali uzatadi. onDraw() ichida clipBounds tekshirilishi va faqat shu hudud chegarasida chizish mumkin, garchi Android Canvas avtomatik ravishda dirty to'rtburchakdan tashqaridagi chizishni kesib tashlaydi.
// Qisman yangilash: faqat kursor maydoni
private val cursorRect = Rect()
fun moveCursorTo(newX: Int, newY: Int) {
// Eski pozitsiyani bekor qilish
invalidate(cursorRect)
cursorRect.set(newX - 5, newY - 5,
newX + 5, newY + 5)
// Yangi pozitsiyani bekor qilish
invalidate(cursorRect)
}
Qisman qayta chizishsiz, har bir kursor harakati butun View-ni qayta chizadi, bu katta grafik uchun bir necha o'nlab o'rniga minglab piksellarning qayta chizilishi degani. invalidate(Rect) — muharrirlar, chizish canvaslari va animatsiya qilingan komponentlar uchun majburiy texnika.
Keng tarqalgan xatolardan biri requestLayout() ni invalidate() yetarli bo'lgan joyda chaqirish va aksincha. Farq asosiy: invalidate() faqat draw fazasiga ta'sir qiladi, requestLayout() esa to'liq measure → layout → draw siklini ishga tushiradi.
| Aspekt | invalidate() | requestLayout() |
|---|---|---|
| Sikl fazalari | Faqat draw | measure + layout + draw |
| Qachon ishlatish | Faqat chizish o'zgaradi (rang, matn, grafik) | Ko'rinishning o'lchami yoki joylashuvi o'zgaradi |
| Ishlash | Yengil — faqat qayta chizish | Og'ir — iyerarxiyani qayta hisoblash |
| Iyerarxiyaga ta'sir | Faqat joriy ko'rinish | Ota konteynerlarga ta'sir qilishi mumkin |
TextView da matnni o'zgartirsangiz — invalidate() yetarli, chunki ko'rinishning o'lchami o'zgarmaydi. Agar matn yangi qatorga o'tib balandlikni oshirishi mumkin bo'lsa — requestLayout() kerak. Android Lint ishlash qoidalari orqali bunday xatolarni kuzatishga yordam beradi.
Haddan tashqari invalidate() chaqiruvlari — Android-da maxsus View-larning past ishlashining asosiy sabablaridan biridir. Optimallashtirish texnikalarini ko'rib chiqaylik.
Agar ma'lumotlar yuqori chastota bilan yangilansa (datchiklar, animatsiya, video), har bir o'zgarishda invalidate() chaqirmang. Ekran yangilanish chastotasi bilan sinxronlash uchun ValueAnimator yoki Choreographer.FrameCallback dan foydalaning. Bu invalidate() har bir kadrda bir martadan ko'p chaqirilmasligini kafolatlaydi.
API 14 dan boshlab Android GPU orqali apparat tezlashtirishni qo'llab-quvvatlaydi. Agar maxsus View faqat Canvas API (drawRect, drawCircle, drawPath) ishlatsa, tezlashtirish shaffof ishlaydi. DisplayList-ga mos operatsiyalar uchun invalidate() sezilarli darajada tezroq ishlanadi.
// Vsync sinxronlash uchun Choreographer dan foydalanish
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
updateAnimation(frameTimeNanos)
invalidate()
Choreographer.getInstance().postFrameCallback(this)
}
fun startAnimation() {
Choreographer.getInstance().postFrameCallback(frameCallback)
}
Nuqtaviy yangilanishlar uchun invalidate(Rect) dan foydalaning, onDraw() ichidan invalidate() chaqirishdan saqlaning (cheksiz sikl) va har doim qurilmada GPU Profile Rendering orqali profil oling. Bu har bir kadrning chizilish vaqtini ko'rsatadi va muammoli joylarni aniqlashga yordam beradi.
Tez-tez so'raladigan savollar
Yo'q, onDraw() ichida invalidate() chaqiruvi cheksiz qayta chizish siklini yaratadi: onDraw() invalidate() chaqiradi, bu yana onDraw() ni ishga tushiradi. Bu CPU ning 100% yuklanishiga va kadr yo'qotilishiga olib keladi. ValueAnimator yoki Choreographer orqali animatsiyalardan foydalaning.
invalidate() faqat UI thread-da ishlaydi va dirty flag-ni darhol yangilaydi. postInvalidate() Handler orqali UI thread-ga so'rov yuboradi va istalgan fon thread-dan chaqirilishi mumkin. UI thread-da bo'lsangiz — minimal kechikish uchun invalidate() dan foydalaning.
Ha, TextView ichida setText() matn yangilangandan so'ng invalidate() chaqiradi. Agar matn ko'rinishning o'lchamlarini o'zgartirgan bo'lsa, qo'shimcha ravishda requestLayout() chaqiriladi. Standart vidjetlar bilan ishlaganda dasturchi qo'lda invalidate() chaqirishi shart emas.
Har bir invalidate() chaqiruvi keyingi Vsync da (har 16 ms) qayta chizishni rejalashtiradi. Agar onDraw() 16 ms dan uzoq davom etsa, kadr yo'qotilishi sodir bo'ladi. onDraw() ni optimallashtiring — Bitmap ni keshlang, ajratmalardan qoching va GPU chizish uchun Hardware Acceleration dan foydalaning.
Ha, Paint xususiyatlarini (rang, qalinlik, uslub) o'zgartirgandan keyin invalidate() chaqirish kerak, chunki View Paint ob'ektlaridagi o'zgarishlarni avtomatik kuzatmaydi. Tizim Paint o'zgarganini bilmaydi va aniq so'rovsiz onDraw() ni chaqirmaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.