2018 년 말이 되서 상황이 바뀌 었습니다.
우선 : 앱을 실행하고 Android Studio에서 Android 프로파일 러 탭을 엽니 다. 당신은 얼마나 많은 메모리를 소비하는지 볼 것입니다, 당신은 놀랄 것이지만 많은 RAM을 할당 할 수 있습니다.
또한 여기에는 메모리 관리에 대한 심층적 인 모양을 제공 할 수있는 메모리 프로파일 러 사용 방법에 대한 자세한 지침이 포함 된 공식 문서의 유용한 기사 가 있습니다.
그러나 대부분의 경우 일반 Android 프로파일 러로 충분합니다.
일반적으로 앱은 50Mb의 RAM 할당으로 시작하지만 메모리에 일부 사진을로드하기 시작하면 즉시 90Mb까지 점프합니다. 미리로드 된 사진 (각각 3,5Mb)이있는 ViewPager로 활동을 열면 몇 초 만에 190Mb를 쉽게 얻을 수 있습니다.
그러나 이것이 메모리 관리에 문제가 있다는 것을 의미하지는 않습니다.
내가 줄 수있는 최선의 조언은 가이드 라인과 모범 사례를 따르고 이미지 로딩을 위해 최고의 라이브러리를 사용하는 것입니다 (Glide, Picasso).
그러나 무언가를 조정해야하고 실제로 수동으로 할당 할 수있는 메모리 양을 알아야하는 경우 총 여유 메모리를 확보하고 사전 결정된 부분 (%)을 계산할 수 있습니다. 필자의 경우, 해독 된 사진을 메모리에 캐시해야했기 때문에 사용자가 목록을 슬라이드 할 때마다 해독 할 필요가 없습니다.
이를 위해 LruCache 클래스 를 사용할 수 있습니다 . 그것은 객체가 얼마나 많은 메모리를 할당했는지 (또는 인스턴스 수)를 자동으로 추적하고 최근 사용 내역으로 최신을 유지하기 위해 가장 오래된 메모리를 제거하는 캐시 클래스입니다.
다음은 사용법에 대한 훌륭한 자습서입니다.
필자의 경우 엄지와 첨부 파일을 위해 두 개의 캐시 인스턴스를 만들었습니다. 싱글 톤 액세스로 정적으로 만들었으므로 전 세계 앱에서 사용할 수 있습니다.
캐시 클래스 :
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;
}
}
이것은 사용 가능한 여유 RAM을 계산하는 방법과 그것을 얼마나 많이 물릴 수 있는지입니다.
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);
내 앱은 API 19 이상을 대상으로하므로 장치가 오래되지 않았으며 사용 가능한 RAM 의이 부분은 내 경우에는 캐시에 충분합니다 (1 % 및 3 %).
재미있는 사실 : Android에는 앱에 할당 된 메모리 양을 가져 오는 API 또는 기타 해킹이 없으며 다양한 요소를 기반으로 즉시 계산됩니다.
추신 : 나는 정적 클래스 필드를 사용하여 캐시를 보유하고 있지만 최신 Android 지침에 따라 해당 목적으로 ViewModel 아키텍처 구성 요소 를 사용하는 것이 좋습니다 .