यह 2018 का अंत है इसलिए चीजें बदल गई हैं।
सबसे पहले: अपना ऐप चलाएं और Android Studio में Android Profiler टैब खोलें। आप देखेंगे कि यह कितनी मेमोरी खपत करता है, आपको आश्चर्य होगा लेकिन यह बहुत सारी रैम आवंटित कर सकता है।
साथ ही यहाँ एक बेहतरीन लेख है आधिकारिक में है जिसमें मेमोरी प्रोइलर का उपयोग करने के बारे में विस्तृत निर्देश दिए गए हैं जो आपको आपके स्मृति प्रबंधन का गहराई से विवरण दे सकते हैं।
लेकिन ज्यादातर मामलों में, आपका नियमित एंड्रॉइड प्रोफाइलर आपके लिए पर्याप्त होगा।
आमतौर पर, एक ऐप 50Mb RAM आवंटन के साथ शुरू होता है, लेकिन मेमोरी में कुछ फ़ोटो लोड करने पर तुरंत 90Mb तक उछल जाता है। जब आप पहले से देखे गए फ़ोटो (3,5Mb प्रत्येक) के साथ एक ViewPager के साथ गतिविधि खोलते हैं, तो आप सेकंड में 190Mb आसानी से प्राप्त कर सकते हैं।
लेकिन इसका मतलब यह नहीं है कि आपके पास स्मृति प्रबंधन के साथ समस्याएँ हैं।
सबसे अच्छी सलाह जो मैं दे सकता हूं वह है दिशा-निर्देशों और सर्वोत्तम प्रथाओं का पालन करना, छवि लोडिंग (ग्लाइड, पिकासो) के लिए शीर्ष पुस्तकालयों का उपयोग करना और आप ठीक होंगे।
लेकिन अगर आपको कुछ करने की आवश्यकता है और आपको वास्तव में यह जानने की आवश्यकता है कि आप कितनी मेमोरी मैन्युअल रूप से आवंटित कर सकते हैं तो आप कुल मुफ्त मेमोरी प्राप्त कर सकते हैं और उसमें से पूर्व-निर्धारित हिस्से (% में) की गणना कर सकते हैं। मेरे मामले में, मुझे मेमोरी में डिक्रिप्ट किए गए फ़ोटो को कैश करने की आवश्यकता थी, इसलिए मुझे सूची के माध्यम से उन्हें हर उपयोगकर्ता स्लाइड को डीक्रिप्ट करने की आवश्यकता नहीं है।
इस प्रयोजन के लिए आप LruCache वर्ग का उपयोग करने के लिए तैयार उपयोग कर सकते हैं । यह एक कैश क्लास है जो स्वचालित रूप से ट्रैक करता है कि आपकी ऑब्जेक्ट कितनी मेमोरी (या इंस्टेंस की संख्या) आवंटित करती है और अपने उपयोग के इतिहास द्वारा हाल ही में रखने के लिए सबसे पुराने को हटा देती है।
यहां इसका उपयोग करने के तरीके पर एक महान ट्यूटोरियल है।
मेरे मामले में, मैंने कैश के 2 उदाहरण बनाए: अंगूठे और संलग्नक के लिए। उन्हें सिंगलटन एक्सेस के साथ स्थिर बना दिया ताकि वे पूरे ऐप में विश्व स्तर पर उपलब्ध हों।
कैश क्लास:
public class BitmapLruCache extends LruCache<Uri, byte[]> {
private static final float CACHE_PART_FOR_THUMBS_PRC = 0.01f; // 1% (Nexus 5X - 5Mb)
private static final float CACHE_PART_FOR_ATTACHMENTS_PRC = 0.03f;// 3% (Nexus 5X - 16Mb)
private static BitmapLruCache thumbCacheInstance;
private static BitmapLruCache attachmentCacheInstance;
public static synchronized BitmapLruCache getDecryptedThumbCacheInstance() {
if (thumbCacheInstance == null) {
int cacheSize = getCacheSize(CACHE_PART_FOR_THUMBS_PRC);
//L.log("creating BitmapLruCache for Thumb with size: " + cacheSize + " bytes");
thumbCacheInstance = new BitmapLruCache(cacheSize);
return thumbCacheInstance;
} else {
return thumbCacheInstance;
}
}
public static synchronized BitmapLruCache getDecryptedAttachmentCacheInstance() {
if (attachmentCacheInstance == null) {
int cacheSize = getCacheSize(CACHE_PART_FOR_ATTACHMENTS_PRC);
// L.log("creating BitmapLruCache for Attachment with size: " + cacheSize + " bytes");
attachmentCacheInstance = new BitmapLruCache(cacheSize);
return attachmentCacheInstance;
} else {
return attachmentCacheInstance;
}
}
private BitmapLruCache(int maxSize) {
super(maxSize);
}
public void addBitmap(Uri uri, byte[] bitmapBytes) {
if (get(uri) == null && bitmapBytes != null)
put(uri, bitmapBytes);
}
public byte[] getBitmap(Uri uri) {
return get(uri);
}
@Override
protected int sizeOf(Uri uri, byte[] bitmapBytes) {
// The cache size will be measured in bytes rather than number of items.
return bitmapBytes.length;
}
}
यह है कि मैं उपलब्ध मुक्त रैम की गणना करता हूं और मैं इसे कितना काट सकता हूं:
private static int getCacheSize(float partOfTotalFreeMemoryToUseAsCache){
final long maxMemory = Runtime.getRuntime().maxMemory();
//Use ... of available memory for List Notes thumb cache
return (int) (maxMemory * partOfTotalFreeMemoryToUseAsCache);
}
और यह है कि मैं कैश्ड छवि प्राप्त करने के लिए एडेप्टर में इसका उपयोग करता हूं:
byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);
और कैसे मैंने इसे कैश इन बैकग्राउंड थ्रेड (नियमित रूप से AsyncTask) में सेट किया:
BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes);
मेरा ऐप एपीआई 19+ को लक्षित करता है ताकि डिवाइस पुराने न हों और उपलब्ध रैम के ये अंश मेरे मामले में (1% और 3%) कैश के लिए पर्याप्त हैं।
मजेदार तथ्य: एंड्रॉइड के पास आपके ऐप को आवंटित मेमोरी की मात्रा प्राप्त करने के लिए कोई एपीआई या अन्य हैक नहीं है, इसकी गणना विभिन्न कारकों के आधार पर फ्लाई पर की जाती है।
PS मैं एक स्थिर वर्ग फ़ील्ड का उपयोग कैश रखने के लिए कर रहा हूं लेकिन नवीनतम Android दिशानिर्देशों के अनुसार इसके लिए ViewModel आर्किटेक्चर घटक का उपयोग करने की सिफारिश की गई है ।