Android 2D रेंडरिंग पाइपलाइन, हार्डवेयर से तेज़ी लाने की सुविधा के साथ काम करती है. इसका मतलब है कि कैनवस पर किए जाने वाले सभी ड्रॉइंग ऑपरेशन, जीपीयू का इस्तेमाल करते हैं. हार्डवेयर से तेज़ी लाने की सुविधा चालू करने के लिए, ज़्यादा संसाधनों की ज़रूरत होती है. इसलिए, आपका ऐप्लिकेशन ज़्यादा रैम इस्तेमाल करेगा.
हार्डवेयर से तेज़ी लाने की सुविधा डिफ़ॉल्ट रूप से चालू होती है. अगर आपका ऐप्लिकेशन सिर्फ़ स्टैंडर्ड कंपोज़ेबल का इस्तेमाल करता है, तो इसे ग्लोबल तौर पर चालू करने से ड्रॉइंग पर कोई बुरा असर नहीं पड़ेगा. हालांकि, हार्डवेयर की मदद से रेंडरिंग की सुविधा, 2D ड्राइंग के सभी ऑपरेशन के लिए उपलब्ध नहीं है. इसलिए, इसे चालू करने पर, कस्टम ड्राइंग के कुछ कॉल पर असर पड़ सकता है. समस्याएं आम तौर पर, न दिखने वाले एलिमेंट, अपवाद या गलत तरीके से रेंडर किए गए पिक्सल के तौर पर दिखती हैं. इस समस्या को ठीक करने के लिए, Android आपको कई लेवल पर हार्डवेयर से तेज़ी लाने की सुविधा को चालू या बंद करने का विकल्प देता है. हार्डवेयर से तेज़ी लाने की सुविधा को कंट्रोल करना लेख पढ़ें.
अगर आपका ऐप्लिकेशन कस्टम ड्राइंग करता है, तो अपने ऐप्लिकेशन को हार्डवेयर से तेज़ी लाने की सुविधा चालू करके, असली हार्डवेयर डिवाइसों पर टेस्ट करें. इससे आपको किसी भी समस्या का पता लगाने में मदद मिलेगी. ड्राइंग ऑपरेशन के लिए सहायता सेक्शन में, हार्डवेयर की मदद से तेज़ी लाने की सुविधा से जुड़ी ज्ञात समस्याओं के बारे में बताया गया है. साथ ही, उन्हें हल करने का तरीका भी बताया गया है.
फ़्रेमवर्क एपीआई के साथ OpenGL भी देखें.
हार्डवेयर की मदद से तेज़ी लाने की सुविधा को कंट्रोल करना
हार्डवेयर से तेज़ी लाने की सुविधा को इन लेवल पर कंट्रोल किया जा सकता है:
- ऐप्लिकेशन
- गतिविधि
- विंडो
- कंपोज़ेबल
ऐप्लिकेशन लेवल
अपने पूरे ऐप्लिकेशन के लिए हार्डवेयर ऐक्सेलरेटेड रेंडरिंग की सुविधा चालू करने के लिए, अपनी Android मेनिफ़ेस्ट फ़ाइल में <application> टैग में यह एट्रिब्यूट जोड़ें:
<application android:hardwareAccelerated="true" ...>
गतिविधि का लेवल
अगर हार्डवेयर ऐक्सलरेशन को ग्लोबल लेवल पर चालू करने पर, आपका ऐप्लिकेशन ठीक से काम नहीं करता है, तो इसे अलग-अलग गतिविधियों के लिए भी कंट्रोल किया जा सकता है. गतिविधि के लेवल पर हार्डवेयर से तेज़ी लाने की सुविधा को चालू या बंद करने के लिए, <activity> एलिमेंट के लिए android:hardwareAccelerated एट्रिब्यूट का इस्तेमाल किया जा सकता है. यहां दिए गए उदाहरण में, पूरे ऐप्लिकेशन के लिए हार्डवेयर की मदद से तेज़ी लाने की सुविधा चालू की गई है. हालांकि, इसे एक ऐक्टिविटी के लिए बंद कर दिया गया है:
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
विंडो लेवल
अगर आपको ज़्यादा कंट्रोल की ज़रूरत है, तो यहां दिए गए कोड की मदद से, किसी विंडो के लिए हार्डवेयर से तेज़ी लाने की सुविधा चालू की जा सकती है:
window.setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
)
कंपोज़ेबल लेवल
Compose में, हार्डवेयर की मदद से तेज़ी लाने की सुविधा को बंद करने के लिए, हर कंपोज़ेबल के हिसाब से कोई स्विच नहीं होता है.
किसी कंपोज़ेबल को उसकी लेयर में रेंडर करने के लिए, Modifier.graphicsLayer का इस्तेमाल करें. इससे, कंपोज़ेबल के ड्रॉइंग कोड को फिर से चलाए बिना, ट्रांसफ़ॉर्म प्रॉपर्टी (जैसे कि alpha, scaleX, scaleY, translationX, translationY, rotationX, rotationY, rotationZ, और transformOrigin) में बदलाव किया जा सकता है. बेहतर परफ़ॉर्मेंस के लिए, इन प्रॉपर्टी को सेट करते समय हमेशा मॉडिफ़ायर के लैम्डा फ़ॉर्म का इस्तेमाल करें.
एडवांस ड्राइंग ऑपरेशन के लिए, स्क्रीन से बाहर मौजूद बफ़र को साफ़ तौर पर लागू करने के लिए CompositingStrategy.Offscreen का इस्तेमाल करें. जैसे, लेयर में कस्टम ब्लेंडिंग.
ज़्यादा जानकारी के लिए, ग्राफ़िक्स मॉडिफ़ायर देखें.
अगर आपको कस्टम ड्राइंग ऑपरेशन करना है और इसके लिए सॉफ़्टवेयर रेंडरिंग की ज़रूरत है, तो AndroidView का इस्तेमाल करके लेगसी व्यू को होस्ट किया जा सकता है. इसके बाद, उस व्यू पर setLayerType(View.LAYER_TYPE_SOFTWARE, null) को कॉल किया जा सकता है.
ड्रॉ करने की कार्रवाइयों के लिए सहायता
हार्डवेयर की मदद से रेंडर किए जाने पर, 2D रेंडरिंग पाइपलाइन, Canvas ड्राइंग के सबसे ज़्यादा इस्तेमाल किए जाने वाले ऑपरेशन के साथ-साथ, कम इस्तेमाल किए जाने वाले कई ऑपरेशन भी सपोर्ट करती है. Android के साथ शिप होने वाले ऐप्लिकेशन, स्टैंडर्ड कंपोज़ेबल, और सामान्य तौर पर इस्तेमाल होने वाले बेहतर विज़ुअल इफ़ेक्ट, जैसे कि रिफ़्लेक्शन और टाइल वाली बनावट को रेंडर करने के लिए इस्तेमाल किए जाने वाले सभी ड्रॉइंग ऑपरेशन काम करते हैं.
यहां दी गई टेबल में, एपीआई के अलग-अलग लेवल पर, अलग-अलग कार्रवाइयों के लिए सहायता के लेवल के बारे में बताया गया है:
| एपीआई का पहला लेवल | ||||
| कैनवस | ||||
| drawBitmapMesh() (colors array) | 18 | |||
| drawPicture() | 23 | |||
| drawPosText() | 16 | |||
| drawTextOnPath() | 16 | |||
| drawVertices() | 29 | |||
| setDrawFilter() | 16 | |||
| clipPath() | 18 | |||
| clipRegion() | 18 | |||
| clipRect(Region.Op.XOR) | 18 | |||
| clipRect(Region.Op.Difference) | 18 | |||
| clipRect(Region.Op.ReverseDifference) | 18 | |||
| रोटेशन/पर्सपेक्टिव के साथ clipRect() | 18 | |||
| पेंट | ||||
| setAntiAlias() (टेक्स्ट के लिए) | 18 | |||
| setAntiAlias() (लाइनों के लिए) | 16 | |||
| setFilterBitmap() | 17 | |||
| setLinearText() | ✗ | |||
| setMaskFilter() | ✗ | |||
| setPathEffect() (लाइनें बनाने के लिए) | 28 | |||
| setShadowLayer() (टेक्स्ट के अलावा) | 28 | |||
| setStrokeCap() (लाइनों के लिए) | 18 | |||
| setStrokeCap() (पॉइंट के लिए) | 19 | |||
| setSubpixelText() | 28 | |||
| Xfermode | ||||
| PorterDuff.Mode.DARKEN (framebuffer) | 28 | |||
| PorterDuff.Mode.LIGHTEN (फ़्रेमबफ़र) | 28 | |||
| PorterDuff.Mode.OVERLAY (फ़्रेमबफ़र) | 28 | |||
| शेडर | ||||
| ComposeShader के अंदर ComposeShader | 28 | |||
| ComposeShader में एक ही तरह के शेडर | 28 | |||
| ComposeShader पर लोकल मैट्रिक्स | 18 | |||
कैनवस को स्केल करना
हार्डवेयर की मदद से तेज़ की गई 2D रेंडरिंग पाइपलाइन को सबसे पहले, बिना स्केल किए ड्राइंग करने की सुविधा देने के लिए बनाया गया था. इसमें ड्राइंग से जुड़ी कुछ कार्रवाइयों की क्वालिटी, ज़्यादा स्केल वैल्यू पर काफ़ी खराब हो जाती है. इन कार्रवाइयों को, स्केल 1.0 पर बनाए गए टेक्सचर के तौर पर लागू किया जाता है. इन्हें जीपीयू से बदला जाता है. एपीआई लेवल 28 से, ड्रॉइंग से जुड़ी सभी कार्रवाइयों को बिना किसी समस्या के स्केल किया जा सकता है.
नीचे दी गई टेबल में बताया गया है कि बड़े पैमाने पर डेटा को सही तरीके से मैनेज करने के लिए, कब लागू करने का तरीका बदला गया:
| ड्रॉइंग ऑपरेशन को स्केल किया जाना है | एपीआई का पहला लेवल |
| drawText() | 18 |
| drawPosText() | 28 |
| drawTextOnPath() | 28 |
| सामान्य आकार | 17 |
| मुश्किल शेप | 28 |
| drawPath() | 28 |
| शैडो लेयर | 28 |
अगर आपकी ज़रूरत के हिसाब से कोई ड्रॉइंग ऑपरेशन, हार्डवेयर की मदद से तेज़ी से नहीं हो रहा है, तो उस ड्रॉइंग को स्क्रीन से बाहर मौजूद सॉफ़्टवेयर Bitmap (या ImageBitmap) में रेंडर करें और नतीजे को ड्रॉ करें. आपके बाकी यूज़र इंटरफ़ेस (यूआई) में, हार्डवेयर की मदद से रेंडर करने की सुविधा चालू रहती है.
सुझाव और तरकीबें
हार्डवेयर की मदद से रेंडर किए जाने वाले 2D ग्राफ़िक पर स्विच करने से, परफ़ॉर्मेंस तुरंत बेहतर हो सकती है. हालांकि, आपको अपने ऐप्लिकेशन को इस तरह से डिज़ाइन करना चाहिए कि वह GPU का असरदार तरीके से इस्तेमाल कर सके. इसके लिए, इन सुझावों का पालन करें:
- लेआउट की जटिलता और रीकंपोज़िशन को कम करना
- लेआउट ट्री को छोटा रखें और कम से कम रीकंपोज़ करें. स्टेट को सबसे छोटे स्कोप में पढ़ें, ताकि बदलाव होने पर सबसे छोटे क्षेत्र को फिर से रेंडर किया जा सके. उदाहरण के लिए, कंपोज़ेबल के मुख्य हिस्से के बजाय
Modifier.graphicsLayer { }में ऐनिमेशन की स्थिति को पढ़ें. ज़्यादा जानकारी के लिए, Jetpack Compose की परफ़ॉर्मेंस देखें. - ओवरड्रॉ से बचें
- एक-दूसरे के ऊपर बहुत ज़्यादा लेयर न बनाएं. ऐसे यूज़र इंटरफ़ेस (यूआई) एलिमेंट हटाएं जो पूरी तरह से छिपे हुए हैं. ऐसा इसलिए, क्योंकि उनके ऊपर मौजूद अन्य एलिमेंट पारदर्शी नहीं हैं. अगर आपको एक-दूसरे के ऊपर ब्लेंड की गई कई लेयर बनानी हैं, तो उन्हें एक ही लेयर में मर्ज करें. मौजूदा हार्डवेयर के लिए, यह एक अच्छा नियम है कि स्क्रीन पर हर फ़्रेम में पिक्सल की संख्या, स्क्रीन पर मौजूद पिक्सल की संख्या के 2.5 गुना से ज़्यादा न हो. हालांकि, बिटमैप में मौजूद पारदर्शी पिक्सल की गिनती की जाती है!
- ड्रॉ करने के तरीकों में रेंडर ऑब्जेक्ट न बनाएं
- आम तौर पर, रेंडरिंग के हर तरीके को लागू करते समय, नया
Paintया नयाPathबनाया जाता है. इससे गार्बेज कलेक्टर को ज़्यादा बार चलाना पड़ता है. साथ ही, यह हार्डवेयर पाइपलाइन में कैश मेमोरी और ऑप्टिमाइज़ेशन को भी बायपास करता है. इससे बचने के लिए, अपने ऑब्जेक्ट का फिर से इस्तेमाल करें और उनमें बदलाव करें:- स्टैंडर्ड तरीकों का इस्तेमाल करें: स्टैंडर्ड
DrawScopeतरीके (जैसे,drawRectऔरdrawCircle) पहले से हीPaintऑब्जेक्ट का फिर से इस्तेमाल करते हैं. इसके लिए, डेवलपर को अलग से अनुमति देने की ज़रूरत नहीं होती. - फिर से असाइन करने के बजाय बदलाव करना: कस्टम लॉजिक लिखते समय, नए
Pathको इंस्टैंशिएट करने के बजाय, मौजूदाPathको मिटाने के लिएpath.rewindका इस्तेमाल करें. - होल्ड स्टेट को असरदार तरीके से मैनेज करना: कंपोज़ेबल के अंदर,
remember { Path() }का इस्तेमाल करके ऑब्जेक्ट को एक बार असाइन करें. अगर आपको फिर से इस्तेमाल की जा सकने वाली कस्टम मॉडिफ़ायर एक्सटेंशन बनानी हैं, तो नए हीप एलोकेशन की वजह से होने वाली समस्याओं से बचने के लिए,DrawModifierNodeका इस्तेमाल करके कस्टमModifier.Nodeलागू करें. इससे ऑब्जेक्ट को असाइन और फिर से इस्तेमाल किया जा सकेगा.
- स्टैंडर्ड तरीकों का इस्तेमाल करें: स्टैंडर्ड
- शेप में बार-बार बदलाव न करें
- उदाहरण के लिए, जटिल आकृतियों, पाथ, और सर्कल को टेक्सचर मास्क का इस्तेमाल करके रेंडर किया जाता है. हर बार जब कोई पाथ बनाया या उसमें बदलाव किया जाता है, तो हार्डवेयर पाइपलाइन एक नया मास्क बनाती है. इसमें ज़्यादा समय लग सकता है.
- बिटमैप में बार-बार बदलाव न करें
- जब भी किसी बिट मैप के कॉन्टेंट में बदलाव किया जाता है, तो उसे अगली बार ड्रॉ करने पर, जीपीयू टेक्सचर के तौर पर फिर से अपलोड किया जाता है.
- ऐल्फ़ा वर्शन का इस्तेमाल सावधानी से करें
Modifier.alphaया Compose ऐनिमेशन एपीआई का इस्तेमाल करके, कंपोज़ेबल को पारदर्शी बनाने पर, आम तौर पर इसे ऑफ़-स्क्रीन बफ़र में रेंडर किया जाता है. इससे, ज़रूरी फ़िल-रेट दोगुना हो जाता है. नॉन-ओवरलैपिंग कॉन्टेंट के लिए, स्क्रीन से बाहर मौजूद बफ़र के ओवरहेड से बचने के लिए,CompositingStrategy.ModulateAlphaसेट करें. अलग-अलग ड्रॉ कॉल के लिए, लेयर बनाए बिना सीधे तौर पर ड्रॉइंग कमांड (जैसे किcolor = Color.Red.copy(alpha = 0.5f)) पर ऐल्फ़ा लागू करें.