इमेज के साथ काम करते समय, परफ़ॉर्मेंस से जुड़ी समस्याएं तुरंत आ सकती हैं. इसलिए, आपको सावधानी बरतनी चाहिए. JPG या PNG जैसे कंप्रेस किए गए फ़ॉर्मैट में मौजूद छोटा ग्राफ़िक भी, डिसप्ले के लिए डिकोड किए जाने पर बड़ा बिटमैप बन सकता है. अगर ग्राफ़िक का सही तरीके से इस्तेमाल नहीं किया जाता है, तो मेमोरी से जुड़ी समस्याएं हो सकती हैं. इससे आपके ऐप्लिकेशन और डिवाइस पर मौजूद अन्य ऐप्लिकेशन की परफ़ॉर्मेंस पर असर पड़ सकता है. यह पक्का करने के लिए कि आपका ऐप्लिकेशन सबसे अच्छा परफ़ॉर्म करे, इन सबसे सही तरीकों को अपनाएं.
इमेज लोड करने वाली लाइब्रेरी का इस्तेमाल करना
इमेज लोड करने वाली लाइब्रेरी का इस्तेमाल करके, अपने ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाया जा सकता है. जैसे, Coil (Kotlin-first प्रोजेक्ट के लिए) या Glide (Java प्रोजेक्ट के लिए). ये लाइब्रेरी, आपके ऐप्लिकेशन की मेमोरी के इस्तेमाल को कम करती हैं. इसके लिए, ये लाइब्रेरी कई काम करती हैं. जैसे, इमेज को कैश मेमोरी में सेव करना, ज़रूरत पड़ने पर ग्राफ़िक को डाउनसैंपल करना, और ग्राफ़िक ऑब्जेक्ट को रीसाइकल करना.
इमेज को डाउनसैंपल करना
पक्का करें कि आपने अपनी ज़रूरत के हिसाब से इमेज का सही साइज़ इस्तेमाल किया हो. आपको छोटे कंटेनर (जैसे कि थंबनेल) में बड़ी और हाई रिज़ॉल्यूशन वाली इमेज लोड करने से बचना चाहिए. इसके बजाय, इमेज को मेमोरी में डिकोड करने से पहले, उसे छोटा करने के लिए डाउनसैंपलिंग का इस्तेमाल करें.
क्लाइंट-साइड डाउनसैंपलिंग
Coil और Glide जैसी इमेज लोड करने वाली लाइब्रेरी, डाउनसैंपलिंग की प्रोसेस को अपने-आप मैनेज करती हैं. ImageLoader (Coil के लिए) या DownsampleStrategy (Glide के लिए) का इस्तेमाल करके, डाउनसैंपलिंग की रणनीतियां कॉन्फ़िगर की जा सकती हैं. अगर बिटमैप को मैन्युअल तरीके से मैनेज किया जा रहा है, तो छोटे वर्शन को डिकोड करने के लिए inSampleSize का इस्तेमाल किया जा सकता है. इसे सुरक्षित तरीके से करने के लिए, आपको सबसे पहले inJustDecodeBounds को true पर सेट करना चाहिए, ताकि मेमोरी को ऐलोकेट किए बिना इमेज के डाइमेंशन पढ़े जा सकें. इसके बाद, सैंपल साइज़ का हिसाब लगाएं, inSampleSize को उस वैल्यू पर सेट करें, inJustDecodeBounds को false पर सेट करें, और फिर इमेज को डिकोड करें.
सर्वर-साइड पर इमेज का साइज़ बदलने की सुविधा को प्राथमिकता देना
जहां भी हो सके, अपने बैकएंड सर्वर से सीधे तौर पर इमेज के सटीक डाइमेंशन का अनुरोध करें. इससे नेटवर्क का इस्तेमाल कम होता है और डिस्क की कैश मेमोरी का फ़ुटप्रिंट कम होता है. साथ ही, डिवाइस पर इमेज का साइज़ बदलने के लिए मेमोरी ओवरहेड से बचने की वजह से, मेमोरी का इस्तेमाल कम होता है.
लाइब्रेरी को इस तरह कॉन्फ़िगर किया जा सकता है कि वे इमेज के यूआरएल में टारगेट व्यू के साइज़ को डाइनैमिक तरीके से जोड़ सकें. उदाहरण के लिए, Coil कस्टम इंटरसेप्टर का इस्तेमाल करके इसकी अनुमति देता है. वहीं, Glide कस्टम मॉडल लोडर (जैसे कि BaseGlideUrlLoader) का इस्तेमाल करके इसकी अनुमति देता है.
लेआउट के साइज़ को सीमित न करने से बचें
इमेज लोड करने वाले टूल को क्लाइंट-साइड या सर्वर-साइड पर इमेज के साइज़ को कम करने के लिए, अनुरोध को पूरा करने से पहले टारगेट साइज़ के बारे में पता होना चाहिए.
रिमोट इमेज लोड करने वाले कंपोज़ेबल पर, wrapContentSize का इस्तेमाल न करें या डाइमेंशन को बिना किसी सीमा के न छोड़ें. अगर ये लाइब्रेरी, टारगेट बाउंड्री का अनुमान नहीं लगा पाती हैं, तो ये पूरी साइज़ वाली ओरिजनल इमेज लोड करती हैं.
इससे ज़रूरत से ज़्यादा बड़ी इमेज लोड हो सकती है. इससे मेमोरी का इस्तेमाल और लेटेन्सी बढ़ जाती है.
इसके बजाय, अपने इमेज कंपोज़ेबल पर डाइमेंशन सेट करें. उदाहरण के लिए, Modifier.size का इस्तेमाल करके या आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) तय करके. इससे लेआउट इंजन, पिक्सल के सटीक टारगेट का हिसाब पहले से लगा पाता है. इसके बाद, इमेज लोडर इसका इस्तेमाल करके, सही साइज़ की ऐसेट का अनुरोध कर सकता है और उसे डिकोड कर सकता है.
अलग-अलग स्क्रीन साइज़ के लिए, वैकल्पिक संसाधन उपलब्ध कराएं
अगर आपको अपने ऐप्लिकेशन के साथ इमेज शिप करनी हैं, तो अलग-अलग डिवाइस रिज़ॉल्यूशन के लिए अलग-अलग साइज़ की ऐसेट उपलब्ध कराएं. इससे डिवाइसों पर आपके ऐप्लिकेशन का डाउनलोड साइज़ कम करने में मदद मिल सकती है. साथ ही, परफ़ॉर्मेंस को बेहतर बनाया जा सकता है, क्योंकि यह कम रिज़ॉल्यूशन वाले डिवाइस पर कम रिज़ॉल्यूशन वाली इमेज लोड करेगा. अलग-अलग डिवाइस साइज़ के लिए, वैकल्पिक बिटमैप उपलब्ध कराने के बारे में ज़्यादा जानने के लिए, वैकल्पिक बिटमैप का दस्तावेज़ देखें.
पैडिंग को सीधे तौर पर लागू न करें
कभी-कभी आपको किसी इमेज में पैडिंग जोड़ने की ज़रूरत पड़ सकती है. उदाहरण के लिए, लेटरबॉक्सिंग के लिए आपको इमेज के चारों ओर पारदर्शी बॉर्डर चाहिए.
ऐसे मामलों में, इमेज के डाइमेंशन में बदलाव करके, सीधे तौर पर इमेज में पैडिंग न जोड़ें. इसके बजाय, इमेज के डाइमेंशन में कोई बदलाव न करें. साथ ही, InsetDrawable का इस्तेमाल करके, स्क्रीन पर इमेज की जगह में बदलाव करें.
इसके अलावा, इमेज को होल्ड करने वाले कंपोज़ेबल या व्यू में पैडिंग जोड़ी जा सकती है.
सही पिक्सल फ़ॉर्मैट चुनना
सही पिक्सल फ़ॉर्मैट चुनकर, मेमोरी और क्वालिटी को बैलेंस करें. अगर आपको पारदर्शिता की ज़रूरत नहीं है, तो RGB_565 का इस्तेमाल करें. यह फ़ॉर्मैट, डिफ़ॉल्ट ARGB_8888 फ़ॉर्मैट की आधी मेमोरी का इस्तेमाल करता है.
Glide में, DecodeFormat का इस्तेमाल करके इसे कॉन्फ़िगर किया जा सकता है. Coil में, bitmapConfig प्रॉपर्टी का इस्तेमाल किया जा सकता है.
जहां भी हो सके वहां वेक्टर का इस्तेमाल करें
ज्यामितीय आकृतियों से बनी इमेज के लिए, वेक्टर ग्राफ़िक, बिटमैप से बहुत छोटा होता है. साथ ही, यह किसी भी डिसप्ले डेंसिटी के लिए आसानी से स्केल हो जाता है. जब सही लगे, तब ग्राफ़िक दिखाने के लिए ShapeDrawable जैसे एलिमेंट का इस्तेमाल करें.
जब भी हो सके, बिटमैप को रिलीज़ करें और उनका फिर से इस्तेमाल करें
बड़ी ग्राफ़िक फ़ाइलों से, ज़्यादा मेमोरी खर्च हो सकती है. इनके असर को कम करने के लिए, जब भी हो सके ग्राफ़िक ऑब्जेक्ट को रिलीज़ करें या उनका फिर से इस्तेमाल करें.
अगर इमेज लोड करने वाली लाइब्रेरी का इस्तेमाल किया जाता है, तो जब आपको बिटमैप की ज़रूरत न हो, तब उन्हें लाइब्रेरी के मैनेज किए गए पूल में रिलीज़ करें. लाइब्रेरी, ज़रूरत पड़ने पर ऑब्जेक्ट का फिर से इस्तेमाल कर सकती है. साथ ही, आने वाले समय में इस्तेमाल करने के लिए मेमोरी बफ़र उपलब्ध कराती है.
अगर ग्राफ़िक को मैन्युअल तरीके से मैनेज किया जा रहा है, तो आपको बिटमैप रिलीज़ करने चाहिए. इसके लिए, Bitmap.recycle को कॉल करें और Bitmap रेफ़रंस को तुरंत खारिज करें. ऐसा गार्बेज कलेक्शन पर भरोसा करने के बजाय करें.
अन्य सुझाव और तरकीबें
इस सेक्शन में, ग्राफ़िक को मैनेज करते समय अपने ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाने के कुछ अन्य तरीके दिए गए हैं.
अपनी AAB/APK फ़ाइल में बड़ी इमेज पैकेज न करें
ऐप्लिकेशन के डाउनलोड साइज़ के ज़्यादा होने की एक मुख्य वजह, AAB या APK फ़ाइल में पैकेज किए गए ग्राफ़िक होते हैं. APK ऐनलिसिस टूल का इस्तेमाल करके यह पक्का करें कि आपने ज़रूरत से ज़्यादा साइज़ वाली इमेज फ़ाइलों को पैकेज नहीं किया है. इमेज का साइज़ कम करें या इमेज को किसी सर्वर पर रखें और सिर्फ़ ज़रूरत पड़ने पर उन्हें डाउनलोड करें.
बेकार के बिटमैप ढूंढना
एक ही इमेज की कई कॉपी होने से, मेमोरी का इस्तेमाल ज़्यादा होता है. Android Studio के प्रोफ़ाइलर का इस्तेमाल करके, ज़रूरत से ज़्यादा ग्राफ़िक का पता लगाया जा सकता है. हीप डंप कैप्चर करने के लिए, हीप डंप ऐनलाइज़र का इस्तेमाल करें. साथ ही, डुप्लीकेट बिटमैप सेटिंग चुनकर, नतीजों को फ़िल्टर करें.
ImageBitmap का इस्तेमाल करते समय, ड्रॉ करने से पहले prepareToDraw को कॉल करें
ImageBitmap का इस्तेमाल करते समय, टेक्सचर को जीपीयू पर अपलोड करने की प्रोसेस शुरू करने के लिए, उसे असल में ड्रॉ करने से पहले ImageBitmap#prepareToDraw() को कॉल करें. इससे जीपीयू को टेक्सचर तैयार करने में मदद मिलती है. साथ ही, स्क्रीन पर विज़ुअल दिखाने की परफ़ॉर्मेंस बेहतर होती है. इमेज लोड करने वाली ज़्यादातर लाइब्रेरी, पहले से ही इस ऑप्टिमाइज़ेशन को करती हैं. हालांकि, अगर ImageBitmap क्लास का इस्तेमाल खुद किया जा रहा है, तो इस बात का ध्यान रखें.
Painter के बजाय, अपने कंपोज़ेबल में पैरामीटर के तौर पर Int DrawableRes या यूआरएल पास करें
इमेज को प्रोसेस करना मुश्किल होता है. उदाहरण के लिए, Bitmaps के लिए बराबर का फ़ंक्शन लिखना, कंप्यूटेशनल तौर पर महंगा होगा. इसलिए, Painter एपीआई को @Stable एनोटेशन के साथ, स्टेबल के तौर पर मार्क नहीं किया गया है. अस्थिर क्लास की वजह से, ज़रूरत न होने पर भी कंपोज़िशन हो सकती हैं. ऐसा इसलिए होता है, क्योंकि कंपाइलर आसानी से यह पता नहीं लगा पाता कि डेटा में बदलाव हुआ है या नहीं.
इसलिए, हमारा सुझाव है कि आप अपने कंपोज़ेबल में, पैरामीटर के तौर पर Painter पास करने के बजाय, यूआरएल या ड्रॉएबल रिसॉर्स आईडी को पैरामीटर के तौर पर पास करें.
// Prefer this:
@Composable
fun MyImage(url: String) {
}
// Over this:
@Composable
fun MyImage(painter: Painter) {
}
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक का टेक्स्ट दिखता है
- ImageBitmap बनाम ImageVector {:#bitmap-vs-vector}
- Compose में यूज़र इंटरफ़ेस (यूआई) की स्थिति सेव करना
- Jetpack Compose के फ़ेज़