onDraw() — bu nima, chaqirish mexanizmi va metodni override qilish

Muallif: IT Sectr Nashr etilgan: 2026-07-22 O'qish vaqti: 10 daq

onDraw() — Android SDK-dagi View sinfining asosiy metodi bo'lib, ko'rinish mazmunini chizish uchun javobgardir. Sistem onDraw-ni View tashqi ko'rinishi har yangilanganda chaqiradi — boshlang'ich render paytida, invalidate() dan so'ng yoki o'lchamlar o'zgarganda. Android Developers Documentation (2026) ga ko'ra, Canvas API yordamida onDraw-ni override qilish Android ilovalarida maxsus grafika yaratishning asosiy usulidir.

Asosiy ma'lumotlar

  • onDraw(Canvas) — sistem tomonidan Canvas-da mazmunni chizish uchun chaqiriladigan View metodi
  • invalidate() — keyingi frame siklida onDraw chaqirilishiga olib keladigan View-ni qayta chizish so'rovi
  • Canvas API drawCircle, drawBitmap, drawText, drawPath va boshqa chizish metodlarini taqdim etadi
  • Android sistemasi chizishni UI oqimida bajaradi, shuning uchun onDraw yengil va tez bo'lishi kerak
  • Hardware acceleration Android 3.0 dan (API 11) boshlab GPU orqali chizishni avtomatik tezlashtiradi

onDraw() nima?

onDraw(Canvas canvas) — bu android.view.View sinfining himoyalangan metodi bo'lib, View render qilinishi kerak bo'lganda Android sistemasi tomonidan chaqiriladi. Dasturchi bu metodni maxsus chizishni amalga oshirish uchun override qiladi: shakllar, matn, rasmlar, gradientlar, animatsiya. Canvas parametri barcha chizish operatsiyalari bajariladigan grafik sirt hisoblanadi.

Metod imzosi oddiy: override fun onDraw(canvas: Canvas). Ushbu metod ichida yangi obyektlar yaratish (GC yukini oldini olish uchun), uzoq operatsiyalarni bajarish yoki tarmoq bilan ishlash mumkin emas. View shuningdek o'z hayot siklida onLayout (pozitsiyalarni hisoblash) va dispatchDraw (bolalar elementlarini chizish) o'rtasida onDraw metodini o'z ichiga oladi.

View dan meros olishda har qanday mazmunni ko'rsatish uchun onDraw-ni override qilish majburiydir — aks holda View bo'sh bo'ladi. Mavjud kichik sinflardan (TextView, ImageView, Button) meros olishda onDraw-ni override qilish ixtiyoriydir va standart mazmun ustiga qo'shimcha grafika qo'shish uchun ishlatiladi.

View chizish sikli

Android View chizishni qat'iy belgilangan tartibda bajaradi, bu tartib asosiy oqimdan (UI thread) chaqiriladi. To'liq sikl uch fazadan iborat: measure (o'lchamlarni o'lchash), layout (pozitsiyalarni hisoblash) va draw (chizish). onDraw draw fazasining bir qismidir va View o'lchamlari va joylashuvi aniqlangandan so'ng chaqiriladi.

Draw fazasi: dispatchDraw va onDraw

draw(Canvas canvas) — bu onDraw va dispatchDraw-ni chaqiradigan View-ning public metodidir. draw metodi override qilish uchun mo'ljallanmagan — uning o'rniga onDraw override qilinadi. Joriy View uchun onDraw bajarilgandan so'ng, dispatchDraw chaqiriladi, u barcha bolalar View-lari uchun draw-ni rekursiv chaqiradi (agar joriy View ViewGroup konteyneri bo'lsa).

Sistem onDraw-ni qachon chaqiradi

onDraw quyidagi shartlarda chaqiriladi: 1) View birinchi marta ko'rinadigan bo'ladi (setVisibility(VISIBLE) dan so'ng); 2) ilova ushbu View yoki uning ota-onasi uchun invalidate() chaqiradi; 3) View o'lchami o'zgaradi (yangi layout); 4) View bilan bog'liq animatsiya o'zgaradi (ValueAnimator yoki ObjectAnimator orqali); 5) View holati o'zgaradi (pressed, focused, enabled).

Apparat tezlashtirish

Android 3.0 (API 11) dan boshlab, ko'pchilik Canvas operatsiyalari GPU orqali apparat tezlashtirish bilan bajariladi. Dasturchi tezlashtirish yoqilganligini canvas.isHardwareAccelerated() orqali tekshirishi mumkin. Apparat tezlashtirishda ba'zi Canvas operatsiyalari qo'llab-quvvatlanmaydi (masalan, to'g'ri to'rtburchak bo'lmagan maydon bilan clipPath) va e'tiborga olinmasligi yoki xatolarga sabab bo'lishi mumkin.

Maxsus grafika uchun Canvas API

Canvas chizish uchun boy metodlar to'plamini taqdim etadi. Barcha metodlar joriy koordinatalar tizimida ishlaydi, bu tizim transformatsiyalar (translate, rotate, scale, skew) orqali o'zgartirilishi mumkin. Har bir metod rang, uslub, chiziq qalinligi, effektlar va tekislashni belgilaydigan Paint obyektini qabul qiladi.

Canvas metodiMaqsadPaint ning asosiy parametrlari
drawCircleDoira chizishcenterX, centerY, radius, paint
drawRectTo'rtburchak chizishleft, top, right, bottom, paint
drawLineChiziq chizishstartX, startY, endX, endY, paint
drawPathIxtiyoriy kontur chizishpath, paint
drawBitmapRasm chizishbitmap, srcRect, dstRect, paint
drawTextMatn chizishtext, x, y, paint
drawArcYoy yoki sektor chizishovalRect, startAngle, sweepAngle, useCenter, paint
drawOvalOval chizishovalRect, paint

Paint obyekti

Paint chizish uslubini belgilaydi: rang (setColor), chiziq qalinligi (setStrokeWidth), to'ldirish uslubi (setStyle — FILL, STROKE, FILL_AND_STROKE), tekislash (setAntiAlias), effektlar (setShadowLayer, setMaskFilter) va gradientlar (setShader). Paint-ni View konstruktorida bir marta yaratish va sozlash tavsiya etiladi, onDraw ichida emas — bu chizish siklida obyekt yaratilishining oldini oladi.

Koordinatalar va transformatsiyalar

Canvas koordinatalar tizimidan foydalanadi, unda X o'qi o'ngga, Y o'qi esa pastga yo'naltirilgan. Koordinatalar boshi (0, 0) View-ning yuqori chap burchagidir. draw metodlarini chaqirishdan oldin dasturchi koordinatalar tizimini canvas.translate(dx, dy), canvas.rotate(degrees, px, py), canvas.scale(sx, sy, px, py) orqali o'zgartirishi mumkin. Barcha keyingi chizish operatsiyalari transformatsiya qilingan tizimda bajariladi.

onDraw unumdorligi

onDraw asosiy UI oqimida bajariladi va uning davomiyligi to'g'ridan-to'g'ri sekundiga kadrlar soniga (fps) ta'sir qiladi. 60 fps ni saqlash uchun onDraw metodi 16 millisekunddan ko'p bo'lmagan vaqtda tugashi kerak. Har qanday sekinlashuv kadrlarning o'tkazib yuborilishiga (jank) olib keladi, bu vizual ravishda animatsiyaning qotib qolishi yoki aylantirishda kechikish sifatida qabul qilinadi.

Samarali onDraw qoidalari

Asosiy qoidalar onDraw optimallashtirishiga quyidagilar kiradi: 1) onDraw ichida obyekt yaratmang — barcha Paint, Path, Rect sinf maydonlari bo'lishi kerak; 2) xotira ajratmang (new) — bu axlat yig'uvchini (GC) ishga tushiradi va kadrlarning o'tkazib yuborilishiga sabab bo'ladi; 3) murakkab operatsiyalarni Bitmap.createBitmap orqali Bitmapda keshlang va tayyor Bitmapni chizing; 4) kirish-chiqish operatsiyalari yoki resurslarni yuklashni bajarmang.

Optimallashtirish uchun clipRect dan foydalanish

clipRect chizish maydonini belgilangan to'rtburchak bilan cheklaydi. Canvas ko'rinadigan maydondan tashqaridagi piksellarni renderlashga vaqt sarflamasligi uchun ishlatiladi. Katta ro'yxatlarni aylantirish yoki masshtablashda ayniqsa samarali: clipRect-ni ko'rinadigan maydonga (dirty rect) o'rnating va Canvas faqat ko'rinadigan narsalarni chizadi.

Layer — saqlash va tiklash

canvas.save() Canvas-ning joriy holatini (transformatsiya va clip) stekda saqlaydi. canvas.restore() oxirgi saqlangan holatni tiklaydi. Bu vaqtinchalik transformatsiyalar uchun zarur: holatni saqlaysiz, translate/rotate qo'llaysiz, chizasiz, keyin tiklaysiz. save va restore yengil va oqilona foydalanishda (10–15 darajadan kam ichki joylashuv) unumdorlikka ta'sir qilmaydi.

invalidate va postInvalidate

invalidate() — bu View metodi bo'lib, sistemaga View mazmuni eskirganligi va uni qayta chizish kerakligi haqida xabar beradi. invalidate chaqiruvi onDraw chaqiriladigan yangi draw siklini boshlaydi. invalidate faqat UI oqimidan (main thread) chaqirilishi kerak. Fon oqimidan chaqirish uchun postInvalidate ishlatiladi.

postInvalidate() — invalidate-ning oqim-xavfsiz versiyasi bo'lib, qayta chizish so'rovini Handler orqali asosiy oqim navbatiga yuboradi. Ma'lumotlarni yuklash yoki hisoblash tugagandan so'ng View-ni yangilash kerak bo'lganda fon vazifalarida ishlatiladi. UI bilan sinxronizatsiya uchun runOnUiThread bilan birlashtiriladi.

Qisman qayta chizish uchun invalidate(Rect dirty) yoki invalidate(int l, int t, int r, int b) ishlatiladi. Bu sistemaga faqat belgilangan maydon o'zgarganligini, butun View emasligini ko'rsatadi. Android faqat dirty rect-ni qayta chizib renderlashni optimallashtiradi, bu qisman yangilanishlar bilan animatsiyalarda unumdorlikni sezilarli darajada oshiradi.

Kotlin kod misollari

Keling, Kotlin yordamida Android uchun maxsus View-lar yaratishda onDraw-ni override qilishning amaliy misollarini ko'rib chiqaylik.

Maxsus View — dumaloq progress

Misol animatsion to'ldirish bilan dumaloq progress ko'rsatkichi yaratadi. onDraw ikkita doira chizadi: kulrang fon va rangli to'ldiriladigan, yoyi joriy progress bilan belgilanadi. setProgress da invalidate chaqiruvi qiymat o'zgarganda qayta chizishni ta'minlaydi.

kotlin
class CircularProgressView
    @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : View(context, attrs) {

    private val bgPaint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 12f
        color = Color.parseColor("#E0E0E0")
        isAntiAlias = true
    }

    private val progressPaint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 12f
        color = Color.BLUE
        isAntiAlias = true
        strokeCap = Paint.Cap.ROUND
    }

    var progress: Float = 0f
        set(value) {
            field = value.coerceIn(0f, 1f)
            invalidate()
        }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val size = minOf(width, height) - 24f
        val oval = RectF(12f, 12f,
                          12f + size, 12f + size)

        canvas.drawArc(oval, 270f, 360f, false, bgPaint)
        canvas.drawArc(oval, 270f,
                        progress * 360f,
                        false, progressPaint)
    }
}

Maxsus View — gradient fonli matn

Misol ustida matn bo'lgan gradient to'rtburchak chizadi. Gradient LinearGradient (Shader) orqali, matn esa drawText orqali yaratiladi. Ikkala Paint konstruktorda bir marta yaratiladi, onDraw da esa faqat to'rtburchak o'lchami joriy View kengligiga qarab o'zgartiriladi.

kotlin
class GradientTextView(context: Context)
    : View(context) {

    private val shaderPaint = Paint().apply {
        isAntiAlias = true
    }

    private val textPaint = Paint().apply {
        color = Color.WHITE
        textSize = 48f
        isAntiAlias = true
        textAlign = Paint.Align.CENTER
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val gradient = LinearGradient(
            0f, 0f, width.toFloat(), 0f,
            Color.parseColor("#FF6B35"),
            Color.parseColor("#FF0040"),
            Shader.TileMode.CLAMP
        )
        shaderPaint.shader = gradient
        canvas.drawRect(0f, 0f,
                        width.toFloat(),
                        height.toFloat(), shaderPaint)

        val xCenter = width / 2f
        val yCenter = height / 2f
        val yOffset = (textPaint.descent() +
                        textPaint.ascent()) / 2f

        canvas.drawText("Canvas dan salom",
                      xCenter, yCenter - yOffset,
                      textPaint)
    }
}

invalidate yordamida animatsion soat

Misol har 1000 millisekundda chizishni yangilaydigan animatsion soat yaratadi. onDraw dagi postDelayed bir soniyadan so'ng invalidate chaqirib, cheksiz qayta chizish siklini yaratadi. Soat millari drawLine orqali turli uzunlik va qalinlikda chiziladi.

kotlin
class AnalogClockView(context: Context)
    : View(context) {

    private val handPaint = Paint().apply {
        style = Paint.Style.STROKE
        isAntiAlias = true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val cx = width / 2f
        val cy = height / 2f
        val radius = minOf(cx, cy) - 20f

        val now = Calendar.getInstance()
        val hours = now.get(Calendar.HOUR) % 12
        val minutes = now.get(Calendar.MINUTE)
        val seconds = now.get(Calendar.SECOND)

        val secondAngle = Math.toRadians(
            seconds * 6f - 90f)
        handPaint.strokeWidth = 2f
        handPaint.color = Color.RED
        canvas.drawLine(cx, cy,
            cx + cos(secondAngle) * radius * 0.8f,
            cy + sin(secondAngle) * radius * 0.8f,
            handPaint)

        postDelayed({ invalidate() }, 1000)
    }
}

Tez-tez so'raladigan savollar

onDraw-ni to'g'ridan-to'g'ri chaqirish mumkinmi?

Yo'q, onDraw-ni to'g'ridan-to'g'ri chaqirish mumkin emas. Qayta chizish so'rovi uchun invalidate() (UI oqimidan) yoki postInvalidate() (fon oqimidan) foydalaning. Sistem o'zi onDraw qachon chaqirilishini hal qiladi va bir nechta invalidate-larni bitta o'tishda birlashtirib renderlashni optimallashtiradi.

Nega onDraw invalidate dan so'ng chaqirilmaydi?

Sabablar: View yashirin (setVisibility(GONE) yoki INVISIBLE); View Window ierarxiyasiga qo'shilmagan; View o'lchami 0 (width yoki height = 0); setWillNotDraw(true) chaqiriladi (ViewGroup uchun sukut bo'yicha true). Nosozliklarni tuzatishda ushbu bandlarning har birini tekshiring.

onDraw qanchalik tez-tez chaqirilishi mumkin?

60 fps da onDraw sekundiga 60 martagacha chaqirilishi mumkin. 120 fps da (120 Hz displeyli qurilmalarda) — 120 martagacha. Har bir chaqiruv ~8–16 millisekundga tugashi kerak. ObjectAnimator yoki ValueAnimator orqali faol animatsiyalarda chastota animatsiya kadrlari soni bilan belgilanadi.

onDraw va dispatchDraw o'rtasidagi farq nima?

onDraw View-ning o'z mazmunini chizish uchun javobgardir. dispatchDraw bolalar View-larini chizish uchun javobgardir (ViewGroup da). dispatchDraw onDraw dan so'ng chaqiriladi va barcha bolalar elementlarini rekursiv ravishda aylanadi. Oddiy View (ViewGroup emas) uchun dispatchDraw bo'sh.

Canvas dan onDraw tashqarisida foydalanish mumkinmi?

Ha, Canvas Canvas(bitmap) orqali Bitmap uchun yaratilishi mumkin va istalgan oqimda chizish mumkin. Bu murakkab grafikani fonda oldindan hisoblash uchun ishlatiladi. Biroq, onDraw da uzatiladigan Canvas sistemaga tegishli va faqat UI oqimida onDraw metodi ichida ishlatilishi mumkin.

Xulosa

  • onDraw(Canvas) — Android da Canvas API yordamida maxsus chizish uchun View ning asosiy metodi
  • Chizish sikli measure, layout va draw fazalaridan iborat — onDraw draw fazasida chaqiriladi
  • Canvas API drawCircle, drawRect, drawPath, drawBitmap, drawText va boshqa metodlarni o'z ichiga oladi
  • invalidate() UI oqimidan, postInvalidate() esa fon oqimidan qayta chizish so'rovi yuboradi
  • Qisman qayta chizish invalidate(Rect) orqali renderlashni optimallashtirib, faqat dirty-maydonni yangilaydi
  • onDraw unumdorligi muhim: metod ichida obyekt yaratish GC va kadr o'tkazib yuborilishiga sabab bo'ladi
  • Apparat tezlashtirish (API 11 dan) GPU orqali Canvas operatsiyalarini avtomatik tezlashtiradi

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.

Loyihani muhokama qilish

Shuningdek o'qing