dispatchDraw(): यह क्या है, कॉल मैकेनिज्म और onDraw से अंतर

लेखक: IT Sectr प्रकाशित: 2026-07-22 पढ़ने का समय: 9 मिनट

dispatchDraw() ViewGroup क्लास का एक मेथड है जो Android पदानुक्रम में सभी चाइल्ड Views की रिकर्सिव ड्रॉइंग के लिए जिम्मेदार है। Android Developers Documentation (2026) के अनुसार, dispatchDraw मुख्य View के draw() मेथड में onDraw के बाद स्वचालित रूप से कॉल किया जाता है और सभी चाइल्ड एलिमेंट्स पर जाकर उनके स्वयं के draw() को कॉल करता है। डेवलपर कस्टम ViewGroups में इफेक्ट्स जोड़ने, चाइल्ड्स के ऊपर ग्राफिक्स लगाने या ड्रॉइंग ऑर्डर बदलने के लिए dispatchDraw को ओवरराइड करते हैं।

मुख्य बिंदु

  • dispatchDraw(Canvas canvas) ViewGroup का एक protected मेथड है जो चाइल्ड Views को ड्रॉ करने के लिए onDraw के बाद कॉल किया जाता है
  • draw(Canvas canvas) View का एक public final मेथड है जो क्रमिक रूप से onDraw, dispatchDraw और onDrawForeground को कॉल करता है
  • onDraw View की स्वयं की सामग्री ड्रॉ करता है, जबकि dispatchDraw सभी चाइल्ड एलिमेंट्स को ड्रॉ करता है
  • setWillNotDraw(true) उन ViewGroups के लिए एक ऑप्टिमाइजेशन है जो अपनी स्वयं की सामग्री नहीं ड्रॉ करते, केवल चाइल्ड एलिमेंट्स ड्रॉ करते हैं
  • dispatchDraw को ओवरराइड करना इफेक्ट्स (blur, overlay) लगाने या चाइल्ड ड्रॉइंग को एनिमेट करने के लिए उपयोग किया जाता है

dispatchDraw() क्या है?

dispatchDraw(Canvas canvas) ViewGroup क्लास का एक protected मेथड है जिसे Android सिस्टम वर्तमान कंटेनर के सभी चाइल्ड Views को ड्रॉ करने के लिए कॉल करता है। dispatchDraw मानक ड्रॉ पाइपलाइन का हिस्सा है: पहले onDraw निष्पादित होता है (View की स्वयं की सामग्री ड्रॉ करना), फिर dispatchDraw (चाइल्ड्स की रिकर्सिव ड्रॉइंग), फिर onDrawForeground (फोरग्राउंड और स्क्रॉलबार ड्रॉ करना)। यह मेथड एप्लिकेशन कोड से सीधे कॉल करने के लिए नहीं है।

ViewGroup में dispatchDraw का मानक कार्यान्वयन सभी चाइल्ड Views पर जाता है, उनकी दृश्यता जाँचता है और प्रत्येक के लिए draw(Canvas) कॉल करता है। ट्रैवर्सल क्रम चाइल्ड इंडेक्स (0 से childCount - 1 तक) के अनुरूप होता है। यदि चाइल्ड Views ओवरलैप होते हैं, तो सूची में बाद वाले पहले वालों के ऊपर ड्रॉ होते हैं। dispatchDraw में क्रम बदलने से ड्रॉइंग का Z-order बदला जा सकता है।

View (ViewGroup नहीं) के लिए, dispatchDraw मेथड खाली है — एक सामान्य View में कोई चाइल्ड एलिमेंट नहीं होते, इसलिए ड्रॉ करने के लिए कुछ नहीं है। यह मेथड बेस View क्लास में मौजूद है लेकिन केवल ViewGroup इंस्टेंस पर कॉल किया जाता है। डेवलपर dispatchDraw के डिफ़ॉल्ट व्यवहार के माध्यम से जाँच सकता है कि View में चाइल्ड एलिमेंट हैं या नहीं, लेकिन अक्सर instanceof ViewGroup जाँचना आसान होता है।

ड्रॉइंग पाइपलाइन: onDraw, dispatchDraw, onDrawForeground

View क्लास का draw(Canvas) मेथड तीन-चरणीय ड्रॉइंग पाइपलाइन व्यवस्थित करता है। पहला चरण onDraw(canvas) कॉल करना है, जहाँ View अपनी सामग्री ड्रॉ करता है। दूसरा चरण dispatchDraw(canvas) कॉल करना है, जो चाइल्ड Views की ड्रॉइंग शुरू करता है। तीसरा चरण onDrawForeground(canvas) है, जो फोरग्राउंड लेयर, स्क्रॉलबार और रिपल इफेक्ट के लिए जिम्मेदार है। यह क्रम ग्राफिकल लेयर्स के सही ओवरले क्रम की गारंटी देता है।

onDraw हमेशा dispatchDraw से पहले निष्पादित होता है। इसका मतलब है कि पैरेंट View की सामग्री चाइल्ड Views के नीचे प्रदर्शित होती है। यदि आपको चाइल्ड्स के ऊपर कुछ ड्रॉ करना है, तो यह onDrawForeground में या ओवरराइड किए गए dispatchDraw में super.dispatchDraw(canvas) कॉल करके और फिर ऊपर ड्रॉ करके किया जाता है। बैकग्राउंड onDraw से पहले भी draw() मेथड के अंदर drawBackground(canvas) में ड्रॉ किया जाता है।

हार्डवेयर एक्सेलेरेशन के साथ, ड्रॉ पाइपलाइन GPU के माध्यम से काम करती है। View को DisplayList में ड्रॉ किया जाता है — ड्रॉ कमांड की एक सूची जो कैश की जाती है और पुनः उपयोग की जाती है। हार्डवेयर-एक्सेलरेटेड मोड में dispatchDraw चाइल्ड Views के DisplayLists को सीन के समग्र DisplayList में जोड़ता है। dispatchDraw को संशोधित करने से DisplayList अमान्य हो सकता है और कैश पुनर्निर्माण हो सकता है, जो प्रदर्शन को प्रभावित करता है।

मेथडकॉल क्रमउद्देश्य
drawBackground1बैकग्राउंड ड्रॉ करना (background drawable)
onDraw2View की स्वयं की सामग्री ड्रॉ करना
dispatchDraw3सभी चाइल्ड Views ड्रॉ करना (केवल ViewGroup)
onDrawForeground4फोरग्राउंड, स्क्रॉलबार और रिपल इफेक्ट ड्रॉ करना

dispatchDraw और onDraw में अंतर

onDraw View की स्वयं की सामग्री — आकार, टेक्स्ट, इमेज जो इस विशिष्ट एलिमेंट से संबंधित हैं — को ड्रॉ करने के लिए जिम्मेदार है। dispatchDraw चाइल्ड Views — ViewGroup के अंदर मौजूद सभी एलिमेंट्स — को ड्रॉ करने के लिए जिम्मेदार है। यदि ViewGroup dispatchDraw को ओवरराइड नहीं करता, तो ViewGroup से कार्यान्वयन का उपयोग किया जाता है, जो केवल childCount पर रिकर्सिव रूप से जाता है और प्रत्येक चाइल्ड के लिए draw कॉल करता है।

उन ViewGroups के लिए जो अपनी स्वयं की सामग्री नहीं ड्रॉ करते (जैसे FrameLayout, LinearLayout), setWillNotDraw(true) सेट करके onDraw को ऑप्टिमाइज़ किया जा सकता है। इस स्थिति में, onDraw कभी कॉल नहीं होता, जो संसाधन बचाता है। dispatchDraw काम करना जारी रखता है और चाइल्ड एलिमेंट्स के लिए draw कॉल करता है। सभी मानक ViewGroups (LinearLayout, RelativeLayout, ConstraintLayout) setWillNotDraw(true) का उपयोग करते हैं।

यदि आप super.dispatchDraw(canvas) कॉल किए बिना dispatchDraw को ओवरराइड करते हैं, तो चाइल्ड Views ड्रॉ नहीं होंगे। यह सभी चाइल्ड्स को अस्थायी रूप से छिपाने के लिए उपयोगी हो सकता है, लेकिन अधिकांश मामलों में यह त्रुटियाँ पैदा करता है। अनुशंसित अभ्यास: ओवरराइड मेथड की शुरुआत में super.dispatchDraw(canvas) कॉल करें, फिर चाइल्ड्स के ऊपर अपने ग्राफिक्स (जैसे अल्फा चैनल के साथ ओवरले) जोड़ें।

Kotlin में dispatchDraw को ओवरराइड करने का उदाहरण

चलिए OverlayViewGroup बनाते हैं — एक कस्टम ViewGroup जो सभी चाइल्ड Views के ऊपर टेक्स्ट लेबल के साथ एक अर्ध-पारदर्शी परत जोड़ता है। dispatchDraw पहले super कॉल करता है (सभी चाइल्ड्स ड्रॉ करना), फिर ओवरले आयत और टेक्स्ट ड्रॉ करता है। Paint कंस्ट्रक्टर में बनाया जाता है ताकि ड्रॉ लूप में आवंटन से बचा जा सके।

kotlin
class OverlayViewGroup(context: Context)
    : ViewGroup(context) {

    private val overlayPaint = Paint().apply {
        color = Color.parseColor("#66000000")
        style = Paint.Style.FILL
    }

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

    init {
        setWillNotDraw(false)
    }

    override fun dispatchDraw(canvas: Canvas) {
        super.dispatchDraw(canvas)
        canvas.drawRect(0f, 0f,
                        width.toFloat(),
                        height.toFloat(), overlayPaint)
        canvas.drawText("पूर्वावलोकन मोड",
            width / 2f,
            height / 2f, textPaint)
    }

    override fun onLayout(changed: Boolean,
                       l: Int, t: Int,
                       r: Int, b: Int) {
        var top = t
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            val cw = child.measuredWidth
            val ch = child.measuredHeight
            child.layout(l, top, l + cw, top + ch)
            top += ch
        }
    }

    override fun onMeasure(widthMeasureSpec: Int,
                       heightMeasureSpec: Int) {
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        val maxWidth = resolveSize(
            getChildAt(0).measuredWidth,
            widthMeasureSpec)
        var totalHeight = 0
        for (i in 0 until childCount) {
            totalHeight += getChildAt(i).measuredHeight
        }
        setMeasuredDimension(maxWidth,
            resolveSize(totalHeight, heightMeasureSpec))
    }
}

dispatchDraw के माध्यम से एनिमेटेड Z-order

निम्नलिखित उदाहरण चाइल्ड एलिमेंट्स के ड्रॉइंग क्रम को बदलने को दर्शाता है। CircularRevealLayout dispatchDraw को ओवरराइड करता है और चाइल्ड्स को उल्टे क्रम में ड्रॉ करता है, जिससे उल्टा Z-order प्रभाव बनता है। एनिमेशन के लिए, एनिमेटेड offset मान के आधार पर ड्रॉइंग इंडेक्स का एक चक्रीय शिफ्ट जोड़ा जाता है।

kotlin
class ReverseOrderLayout(context: Context)
    : ViewGroup(context) {

    private var reverse = false

    override fun dispatchDraw(canvas: Canvas) {
        if (!reverse) {
            super.dispatchDraw(canvas)
            return
        }
        for (i in childCount - 1 downTo 0) {
            val child = getChildAt(i)
            if (child.visibility == GONE) continue
            drawChild(canvas, child, getDrawingTime())
        }
    }

    fun toggleReverse() {
        reverse = !reverse
        invalidate()
    }

    override fun onLayout(changed: Boolean,
                       l: Int, t: Int,
                       r: Int, b: Int) {
        var left = l
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            val cw = child.measuredWidth
            child.layout(left, t,
                left + cw, t + child.measuredHeight)
            left += cw
        }
    }

    override fun onMeasure(widthMeasureSpec: Int,
                       heightMeasureSpec: Int) {
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        var totalWidth = 0
        for (i in 0 until childCount) {
            totalWidth += getChildAt(i).measuredWidth
        }
        setMeasuredDimension(
            resolveSize(totalWidth, widthMeasureSpec),
            resolveSize(getChildAt(0).measuredHeight,
                heightMeasureSpec))
    }
}

Android में dispatchDraw का उपयोग कब करें

dispatchDraw का उपयोग उन परिदृश्यों में किया जाता है जहाँ आपको ViewGroup की स्वयं की सामग्री को प्रभावित किए बिना चाइल्ड Views की ड्रॉइंग प्रक्रिया को प्रभावित करने की आवश्यकता होती है। मुख्य परिदृश्य: सभी चाइल्ड्स के ऊपर एक सामान्य प्रभाव (ओवरले, शैडो, ग्रेडिएंट) लगाना; गहराई प्रभाव बनाने के लिए Z-order बदलना; Canvas ट्रांसफॉर्मेशन के माध्यम से चाइल्ड एलिमेंट्स के प्रकट या अदृश्य होने को एनिमेट करना।

यदि आपको चाइल्ड एलिमेंट्स के नीचे ग्राफिक्स लगाने की आवश्यकता है (बैकग्राउंड इफेक्ट), onDraw का उपयोग करें — dispatchDraw उसके बाद कॉल होता है। यदि ग्राफिक्स चाइल्ड्स के ऊपर होना चाहिए — पहले super कॉल करके, फिर Canvas.draw का उपयोग करके dispatchDraw का उपयोग करें। यदि आपको वैश्विक रंग या पारदर्शिता परिवर्तन की आवश्यकता है, तो dispatchDraw में चाइल्ड्स की ड्रॉइंग को लपेटने के लिए canvas.saveLayerAlpha() का उपयोग करना सुविधाजनक है।

अनुशंसित नहीं है dispatchDraw का उपयोग इसके लिए: 1) रीयल-टाइम में जटिल एनिमेशन ड्रॉ करना (invalidate और onDraw का उपयोग करें); 2) ViewGroup के स्क्रीनशॉट बनाना (buildDrawingCache() या View.draw(Canvas) का उपयोग करें); 3) चाइल्ड Views को संशोधित करना (निर्देशांक, आकार — ये onLayout के कार्य हैं, dispatchDraw के नहीं)। dispatchDraw केवल दृश्य प्रभाव लगाने के लिए है।

अक्सर पूछे जाने वाले प्रश्न

क्या सिस्टम के बिना सीधे dispatchDraw को कॉल किया जा सकता है?

नहीं, dispatchDraw एक protected मेथड है जिसे Android सिस्टम सार्वजनिक draw() मेथड के अंदर कॉल करता है। dispatchDraw का सीधा कॉल अर्थहीन है क्योंकि यह तैयारी क्रियाएँ (Canvas सहेजना, बैकग्राउंड और फोरग्राउंड ड्रॉ करना) नहीं करता। इसके बजाय, प्रोग्रामेटिक रूप से किसी भी Canvas पर ड्रॉ करने के लिए View.draw(Canvas) का उपयोग करें।

कस्टम ड्रॉइंग के बाद super.dispatchDraw कॉल करने पर क्या होता है?

यदि आप अपने स्वयं के ड्रॉइंग ऑपरेशन के बाद super.dispatchDraw(canvas) कॉल करते हैं, तो चाइल्ड Views कस्टम ग्राफिक्स के ऊपर ड्रॉ होंगे। यह लेयर क्रम बदलता है: पहले कस्टम लेयर ड्रॉ होती है, फिर चाइल्ड्स। यदि आपको विपरीत स्थिति चाहिए (चाइल्ड्स के ऊपर ग्राफिक्स), पहले super.dispatchDraw कॉल करें, फिर अपने ऑपरेशन।

dispatchDraw प्रदर्शन को कैसे प्रभावित करता है?

dispatchDraw प्रत्येक चाइल्ड View के लिए draw() कॉल करता है, और कुल समय चाइल्ड्स की संख्या के अनुपात में होता है। हार्डवेयर एक्सेलेरेशन के साथ, dispatchDraw में Canvas ऑपरेशन जोड़ने से DisplayList अमान्य हो सकता है और कैश पुनर्निर्माण हो सकता है। 5–10 चाइल्ड्स के लिए प्रभाव न्यूनतम है, 50+ चाइल्ड्स के लिए जटिल ओवरले को कैश करने की अनुशंसा की जाती है।

View के लिए dispatchDraw क्यों नहीं कॉल होता?

एक View (ViewGroup नहीं) में कोई चाइल्ड एलिमेंट नहीं होते, इसलिए dispatchDraw कोई उपयोगी कार्य नहीं करता। हालाँकि, यह मेथड बेस View क्लास में पॉलीमॉर्फिज़्म के लिए मौजूद है: draw() में कोड किसी भी View के लिए dispatchDraw कॉल करता है, लेकिन View के कार्यान्वयन में चाइल्ड ड्रॉइंग लॉजिक नहीं होता। केवल ViewGroup dispatchDraw को ओवरराइड करता है।

क्या dispatchDraw में Canvas को संशोधित किया जा सकता है?

हाँ, dispatchDraw एक Canvas स्वीकार करता है, और super.dispatchDraw कॉल करने से पहले इसे ट्रांसफॉर्म किया जा सकता है (translate, rotate, scale)। इसका उपयोग चाइल्ड्स के पूरे सेट को एक इकाई के रूप में एनिमेट करने के लिए किया जाता है। super.dispatchDraw पूरा होने के बाद, Canvas को उसकी मूल स्थिति में पुनर्स्थापित करने की अनुशंसा की जाती है।

सारांश

  • dispatchDraw(Canvas) onDraw के बाद सभी चाइल्ड Views की रिकर्सिव ड्रॉइंग के लिए ViewGroup मेथड है
  • ड्रॉ पाइपलाइन: drawBackground → onDraw → dispatchDraw → onDrawForeground
  • onDraw View की स्वयं की सामग्री ड्रॉ करता है, dispatchDraw चाइल्ड एलिमेंट्स की सामग्री ड्रॉ करता है
  • setWillNotDraw(true) onDraw को छोड़कर ViewGroup को ऑप्टिमाइज़ करता है, लेकिन dispatchDraw काम करता रहता है
  • dispatchDraw को ओवरराइड करना इफेक्ट्स लगाने, Z-order बदलने और चाइल्ड्स के Canvas ट्रांसफॉर्मेशन के लिए उपयोग किया जाता है
  • super.dispatchDraw और कस्टम ड्रॉइंग का क्रम निर्धारित करता है कि चाइल्ड्स के ऊपर क्या दिखाई देगा
  • सामान्य View (ViewGroup नहीं) के लिए dispatchDraw खाली है — इसमें कोई चाइल्ड एलिमेंट नहीं होते

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें