Кінець 2018 року, тому все змінилося.
Перш за все: запустіть додаток і відкрийте вкладку Android Profiler в Android Studio. Ви побачите, скільки пам'яті вона споживає, ви здивуєтеся, але це може виділити багато оперативної пам’яті.
Також тут відмінна стаття в офіційних документах з детальними інструкціями щодо використання програми Profiler Memory, яка може дати тобі глибокий погляд на управління пам'яттю.
Але в більшості випадків вам буде достатньо вашого звичайного Android Profiler.
Зазвичай додаток починається з виділення 50 Мб оперативної пам'яті, але миттєво підскакує до 90 Мб, коли ви починаєте завантажувати фотографії в пам'ять. Якщо ви відкриєте «Активність» у ViewPager із попередньо завантаженими фотографіями (3,5 Мбіт кожна), ви легко зможете отримати 190 Мб за секунди.
Але це не означає, що у вас є проблеми з управлінням пам'яттю.
Найкраща порада, яку я можу дати, - це дотримуватися вказівок та найкращих практик, використовувати топ-бібліотеки для завантаження зображень (Glide, Picasso), і ти будеш добре.
Але якщо вам потрібно щось підготувати, і вам дійсно потрібно знати, скільки пам'яті ви можете виділити вручну, ви можете отримати загальну вільну пам'ять і обчислити заздалегідь визначену частину (у%). У моєму випадку мені потрібно було кешувати дешифровані фотографії в пам’яті, тому мені не потрібно розшифровувати їх щоразу, коли користувач ковзає по списку.
Для цього можна використовувати готовий до використання клас 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);
}
Ось так я використовую його в Adapters, щоб отримати кешоване зображення:
byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);
і як я встановив його в кеш у фоновому потоці (звичайний AsyncTask):
BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes);
Мій додаток орієнтовано на API 19+, тому пристрої не старі, і ці частини доступної оперативної пам’яті досить хороші для кешу в моєму випадку (1% та 3%).
Факт забави: Android не має ніяких API та інших хак-файлів, щоб отримати обсяг пам’яті, що виділяється вашому додатку, він розраховується на льоту, виходячи з різних факторів.
PS Я використовую статичне поле класу для зберігання кешу, але відповідно до останніх інструкцій Android рекомендується використовувати для цього компонент архітектури ViewModel .