到了2018年底,情况发生了变化。
首先:运行您的应用程序,然后在Android Studio中打开“ Android Profiler”标签。您会看到它消耗了多少内存,您会感到惊讶,但是它可以分配很多RAM。
另外,这是官方文档中的一篇精彩文章,其中包含有关如何使用Memory Profiler的详细说明,它可以使您对内存管理有更深入的了解。
但是在大多数情况下,常规的Android Profiler就足够了。
通常,一个应用程序以50Mb的RAM分配开始,但是当您开始在内存中加载一些照片时会立即跳至90Mb。使用带有预加载照片的ViewPager(每张照片3Mb)打开“活动”时,您可以在几秒钟内轻松获得190Mb。
但这并不意味着您在内存管理方面存在问题。
我能提供的最佳建议是遵循准则和最佳实践,使用顶级库进行图像加载(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;
}
}
这是我如何计算可用的可用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或其他黑客来获取分配给您的应用程序的内存量,它是根据各种因素动态计算的。
PS我正在使用静态类字段来保存缓存,但是根据最新的Android指南,建议为此目的使用ViewModel体系结构组件。