अगर इमेज का इस्तेमाल सावधानी से नहीं किया जाता है, तो परफ़ॉर्मेंस से जुड़ी समस्याएं तुरंत आ सकती हैं. अगर किसी इमेज को कंप्रेस करके JPG या PNG जैसे फ़ॉर्मैट में सेव किया जाता है, तो डिसप्ले के लिए डिकोड करने पर वह बड़ी बिटमैप इमेज में बदल सकती है. अगर ग्राफ़िक का इस्तेमाल सही तरीके से नहीं किया जाता है, तो मेमोरी से जुड़ी समस्याएं आ सकती हैं. इससे आपके ऐप्लिकेशन और डिवाइस पर मौजूद अन्य ऐप्लिकेशन की परफ़ॉर्मेंस पर असर पड़ सकता है. यह पक्का करने के लिए कि आपका ऐप्लिकेशन बेहतर तरीके से काम करे, इन सबसे सही तरीकों को अपनाएं.
इमेज लोड करने वाली लाइब्रेरी का इस्तेमाल करना
Coil (Kotlin-first प्रोजेक्ट के लिए) या Glide (Java प्रोजेक्ट के लिए) जैसी इमेज लोड करने वाली लाइब्रेरी का इस्तेमाल करके, अपने ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाया जा सकता है. ये लाइब्रेरी, इमेज को कैश मेमोरी में सेव करने, ज़रूरत पड़ने पर ग्राफ़िक का डाउनसैंपल करने, और ग्राफ़िक ऑब्जेक्ट को रीसाइकल करने जैसी कार्रवाइयां करके, आपके ऐप्लिकेशन की मेमोरी के इस्तेमाल को कम करती हैं.
इमेज का डाउनसैंपल करना
पक्का करें कि आपने अपनी ज़रूरत के हिसाब से इमेज का सही साइज़ इस्तेमाल किया हो. आपको किसी छोटे कंटेनर (जैसे कि थंबनेल) में, बड़ी और हाई रिज़ॉल्यूशन वाली इमेज लोड करने से बचना चाहिए. इसके बजाय, इमेज को मेमोरी में डिकोड करने से पहले, उसे स्केल डाउन करने के लिए डाउनसैंपल का इस्तेमाल करें.
क्लाइंट-साइड डाउनसैंपल करना
Coil और Glide जैसी इमेज लोड करने वाली लाइब्रेरी, आपके लिए डाउनसैंपल की प्रोसेस को अपने-आप मैनेज करती हैं. `ImageLoader`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 का इस्तेमाल करें.
जब भी हो सके, बिटमैप को रिलीज़ और रीयूज़ करना
बड़े ग्राफ़िक फ़ाइलें, ज़्यादा मेमोरी ले सकती हैं. इनके असर को कम करने के लिए, जब भी हो सके, ग्राफ़िक ऑब्जेक्ट को रिलीज़ या रीयूज़ करें.
अगर इमेज लोड करने वाली लाइब्रेरी का इस्तेमाल किया जाता है, तो जब आपको बिटमैप की ज़रूरत न हो, तब उन्हें लाइब्रेरी के मैनेज किए गए पूल में रिलीज़ करें. लाइब्रेरी, ज़रूरत पड़ने पर ऑब्जेक्ट को रीयूज़ कर सकती है. साथ ही, भविष्य की ज़रूरतों के लिए मेमोरी बफ़र उपलब्ध रखती है.
अन्य सलाह और सुझाव
इस सेक्शन में, ग्राफ़िक को मैनेज करते समय, अपने ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाने के कुछ अन्य तरीकों के बारे में बताया गया है.
अपने AAB/APK फ़ाइल के साथ बड़ी इमेज पैकेज न करना
ऐप्लिकेशन के डाउनलोड साइज़ के बड़े होने की एक मुख्य वजह, AAB या APK फ़ाइल में पैकेज किए गए ग्राफ़िक होते हैं. यह पक्का करने के लिए कि आपने ज़रूरत से ज़्यादा बड़ी इमेज फ़ाइलें पैकेज न की हों, APK ऐनलिसिस टूल का इस्तेमाल करें. इमेज के साइज़ कम करें या इमेज को किसी सर्वर पर रखने और ज़रूरत पड़ने पर ही उन्हें डाउनलोड करने पर विचार करें.
फ़ालतू बिटमैप ढूंढना
अगर आपके पास एक ही इमेज की कई कॉपी हैं, तो इससे मेमोरी खर्च होती है. फ़ालतू ग्राफ़िक की पहचान करने के लिए, Android Studio के प्रोफ़ाइलर का इस्तेमाल किया जा सकता है. हीप डंप ऐनलिसिस टूल का इस्तेमाल करके, हीप डंप कैप्चर करें. इसके बाद, डुप्लीकेट बिटमैप सेटिंग चुनकर, नतीजों को फ़िल्टर करें.
ImageBitmap का इस्तेमाल करते समय, ड्रॉ करने से पहले prepareToDraw को कॉल करना
ImageBitmap का इस्तेमाल करते समय, टेक्सचर को
जीपीयू पर अपलोड करने की प्रोसेस शुरू करने के लिए, उसे असल में ड्रॉ करने से पहले ImageBitmap#prepareToDraw() को कॉल करें. इससे जीपीयू को टेक्सचर तैयार करने और स्क्रीन पर विज़ुअल दिखाने की परफ़ॉर्मेंस को बेहतर बनाने में मदद मिलती है. ज़्यादातर इमेज लोड करने वाली लाइब्रेरी, इस ऑप्टिमाइज़ेशन को पहले से ही करती हैं. हालांकि, अगर ImageBitmap क्लास के साथ काम किया जा रहा है, तो इस बात का ध्यान रखें.
Painter के बजाय, अपने कंपोज़ेबल में पैरामीटर के तौर पर Int DrawableRes या यूआरएल पास करना
इमेज को मैनेज करने में आने वाली मुश्किलों की वजह से, उदाहरण के लिए, Bitmaps के लिए equals
फ़ंक्शन लिखना, कंप्यूटेशनल तौर पर महंगा होगा. इसलिए, Painter API को
@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 के फ़ेज़