Ini adalah akhir tahun 2018 sehingga banyak hal telah berubah.
Pertama-tama: jalankan aplikasi Anda dan buka tab Android Profiler di Android Studio. Anda akan melihat berapa banyak memori yang dikonsumsi, Anda akan terkejut tetapi dapat mengalokasikan banyak RAM.
Juga di sini adalah artikel yang bagus dalam dokumen resmi dengan instruksi terperinci tentang cara menggunakan Memory Profiler yang dapat memberi Anda pandangan mendalam tentang manajemen memori Anda.
Tetapi dalam sebagian besar kasus, Profiler Android reguler Anda sudah cukup untuk Anda.
Biasanya, aplikasi dimulai dengan alokasi RAM 50 MB tetapi langsung melonjak hingga 90 MB ketika Anda mulai memuat beberapa foto dalam memori. Saat Anda membuka Aktivitas dengan ViewPager dengan foto yang dimuat sebelumnya (masing-masing 3,5Mb), Anda bisa mendapatkan 190Mb dengan mudah dalam hitungan detik.
Tetapi ini tidak berarti Anda memiliki masalah dengan manajemen memori.
Saran terbaik yang bisa saya berikan adalah mengikuti pedoman dan praktik terbaik, gunakan perpustakaan teratas untuk memuat gambar (Glide, Picasso) dan Anda akan baik-baik saja.
Tetapi jika Anda perlu menyesuaikan sesuatu dan Anda benar-benar perlu tahu berapa banyak memori yang dapat Anda alokasikan secara manual, Anda bisa mendapatkan total memori bebas dan menghitung bagian yang telah ditentukan sebelumnya (dalam%) dari itu. Dalam kasus saya, saya perlu men-cache foto yang didekripsi dalam memori sehingga saya tidak perlu mendekripsi mereka setiap kali pengguna menelusuri daftar.
Untuk tujuan ini, Anda dapat menggunakan kelas LruCache siap pakai . Ini adalah kelas cache yang secara otomatis melacak berapa banyak memori yang dialokasikan objek Anda (atau jumlah instance) dan menghapus yang tertua untuk menjaga yang terbaru berdasarkan riwayat penggunaannya.
Berikut adalah tutorial yang bagus tentang cara menggunakannya.
Dalam kasus saya, saya membuat 2 contoh cache: untuk jempol dan lampiran. Jadikan mereka statis dengan akses tunggal sehingga tersedia secara global di seluruh aplikasi.
kelas cache:
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;
}
}
Ini adalah bagaimana saya menghitung RAM gratis yang tersedia dan berapa banyak yang bisa saya gigit darinya:
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);
}
Dan ini adalah bagaimana saya menggunakannya dalam Adaptor untuk mendapatkan gambar dalam tembolok:
byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);
dan bagaimana saya mengaturnya ke dalam cache di latar belakang (AsyncTask biasa):
BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes);
Aplikasi saya menargetkan API 19+ sehingga perangkat tidak lama dan bagian RAM yang tersedia ini cukup baik untuk cache dalam kasus saya (1% dan 3%).
Fakta menyenangkan: Android tidak memiliki API atau peretasan lain untuk mendapatkan jumlah memori yang dialokasikan untuk aplikasi Anda, itu dihitung dengan cepat berdasarkan berbagai faktor.
PS Saya menggunakan bidang kelas statis untuk menyimpan cache tetapi sesuai dengan pedoman Android terbaru direkomendasikan untuk menggunakan komponen arsitektur ViewModel untuk tujuan itu.