Phi*_*oda 140 memory android memory-management out-of-memory android-memory
我对这个关于Android操作系统的内存管理的问题很好奇,所以我希望对这个主题有一个非常详细的答案.
我想知道的是:
最重要的是:
到目前为止我所听到的(直到2013年):
是什么让我很好奇:
这两个限制都非常低.
我刚刚下载了Android任务管理器来检查我的设备RAM.我注意到有些应用程序使用大约40-50兆字节的RAM,这比上面提到的最大RAM使用量(比如说32 MB)要多得多.那么Android如何确定应用程序可以使用多少RAM?应用程序如何超出此限制?
此外,我注意到当使用大约30-40兆字节时,我的一些应用程序崩溃(被系统杀死?)和OutOfMemoryException.另一方面,我的手机上运行的应用程序使用100 MB以上的一段时间后(可能由于内存泄漏)不会崩溃或被杀死.因此,在确定可以节省多少RAM时,显然还取决于应用程序本身.这怎么可能?(我用带有768 MB RAM的HTC One S进行了测试)
免责声明:我不以任何方式与Android任务管理器应用程序相关联.
Com*_*are 118
Android应用程序(不是系统应用程序)可以使用的最大内存量(以兆字节/占总RAM的百分比)是多少?
这取决于设备.getMemoryClass()onActivityManager将为您提供运行代码的设备的值.
Android版本之间有什么区别吗?
是的,就多年来操作系统要求的增加而言,设备必须进行调整才能匹配.
有关设备制造商的差异吗?
是的,就制造商制造设备而言,尺寸因设备而异.
在确定应用程序可以使用多少RAM时,会考虑哪些"因素"?
我不知道"边缘因素"是什么意思.
早期设备的每个应用上限为16MB; 后来的设备增加到24MB或32MB
那是对的.屏幕分辨率是一个重要的决定因素,因为较大的分辨率意味着较大的位图,因此平板电脑和高分辨率手机的价值往往更高.例如,您将看到具有48MB堆的设备,如果有高于此值的值,我不会感到惊讶.
应用程序如何超出此限制?
您假设该应用程序的作者知道他正在做什么.考虑到核心Android工程师很难确定应用程序的内存使用情况,我不会认为有问题的应用程序必然会提供特别准确的结果.
话虽这么说,本机代码(NDK)不受堆限制.而且,从Android 3.0开始,应用程序可以请求"大堆",通常在数百MB的范围内,但对于大多数应用程序而言,这被认为是糟糕的形式.
此外,我注意到当使用大约30-40兆字节时,我的一些应用程序崩溃了OutOfMemoryException.
请记住,Android垃圾收集器不是压缩垃圾收集器.真的应该是例外CouldNotFindSufficientlyLargeBlockOfMemoryException,但这可能被认为过于冗长.OutOfMemoryException意味着您无法分配您请求的块,而不是您完全耗尽了您的堆.
Kir*_*zin 15
到了2018年底,情况发生了变化。
首先:运行您的应用程序,然后在Android Studio中打开“ Android Profiler”标签。您将看到它消耗了多少内存,您会感到惊讶,但是它可以分配很多RAM。
另外,这是官方文档中的一篇精彩文章,其中包含有关如何使用Memory Profiler的详细说明,它可以使您对内存管理有更深入的了解。
但是在大多数情况下,常规的Android Profiler就足够了。
通常,应用程序以50Mb的RAM分配开始,但是当您开始在内存中加载一些照片时,应用程序会立即跳至90Mb。当您使用带有预加载照片的ViewPager(每张3,5Mb)打开“活动”时,可以在几秒钟内轻松获得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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我计算可用空闲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);
}
Run Code Online (Sandbox Code Playgroud)
这就是我在适配器中使用它来获取缓存图像的方式:
byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);
Run Code Online (Sandbox Code Playgroud)
以及如何将其设置为后台线程的缓存(常规AsyncTask):
BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes);
Run Code Online (Sandbox Code Playgroud)
我的应用程序以API 19+为目标,因此设备不是很旧,可用RAM的这些部分足以用于我的情况下的缓存(分别为1%和3%)。
有趣的事实: Android没有任何API或其他黑客来获取分配给您的应用程序的内存量,它是根据各种因素动态计算得出的。
PS我正在使用静态类字段来保存缓存,但是根据最新的Android指南,建议为此目的使用ViewModel体系结构组件。
小智 12
每个应用的内存限制取决于屏幕大小和Android版本:https://drive.google.com/file/d/0B7Vx1OvzrLa3Y0R0X1BZbUpicGc/view?usp=sharing
来源:Android兼容性下载http://source.android.com/compatibility/downloads.html ; 兼容性定义文档(CDD),部分虚拟机兼容性或运行时兼容性
| 归档时间: |
|
| 查看次数: |
64589 次 |
| 最近记录: |