Android:内存不足错误

Android:内存不足错误,android,memory,bitmap,heap,Android,Memory,Bitmap,Heap,当我最小化我的Android应用程序大约4到5次时,我总是会出现以下错误: 02-01 19:24:11.980: E/dalvikvm-heap(22362): Out of memory on a 3686416-byte allocation. 02-01 19:24:12.000: E/dalvikvm(22362): Out of memory: Heap Size=62755KB, Allocated=55237KB, Limit=65536KB 02-01 19:24:12.000

当我最小化我的Android应用程序大约4到5次时,我总是会出现以下错误:

02-01 19:24:11.980: E/dalvikvm-heap(22362): Out of memory on a 3686416-byte allocation.
02-01 19:24:12.000: E/dalvikvm(22362): Out of memory: Heap Size=62755KB, Allocated=55237KB, Limit=65536KB
02-01 19:24:12.000: E/dalvikvm(22362): Extra info: Footprint=62435KB, Allowed Footprint=62755KB, Trimmed=2144KB
02-01 19:24:12.000: E/Bitmap_JNI(22362): Create Bitmap Failed.    
02-01 19:24:12.000: E/Bitmap_JNI(22362): Failed to create SkBitmap!
02-01 19:24:12.000: E/AndroidRuntime(22362): FATAL EXCEPTION: main
02-01 19:24:12.000: E/AndroidRuntime(22362): java.lang.OutOfMemoryError: (Heap Size=62755KB, Allocated=55237KB)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at android.graphics.Bitmap.nativeCreateScaledBitmap(Native Method)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:744)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at de.vauge.mb.Utils.getResizedBitmap(Utils.java:56)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at de.vauge.mb.MenuView.initialize(MenuView.java:74)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at de.vauge.mb.MenuView$1.handleMessage(MenuView.java:137)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at android.os.Looper.loop(Looper.java:156)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at android.app.ActivityThread.main(ActivityThread.java:5045)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at java.lang.reflect.Method.invokeNative(Native Method)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at java.lang.reflect.Method.invoke(Method.java:511)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
02-01 19:24:12.000: E/AndroidRuntime(22362):    at dalvik.system.NativeStart.main(Native Method)
我的应用程序只包含一个活动,其中有7个不同的自述视图(所有视图都包含一些位图),在不需要它们时,它们被切换为不可见(可能不是很好的样式,但直到现在它还适用于我…)。这些视图中的每一个都有一个destroy()函数,该函数循环使用其中使用的所有位图,MainActivity的onDestroy()调用所有这些destroy()函数。此外,我没有使用任何静态位图


那么,除了回收所有位图和不使用静态位图之外,还有什么我可以尝试的吗?

请确保将它们加载到
onCreate()
中,而不是加载到
onStart()
onResume()
中。听起来每次恢复时都会重新加载,但不会被销毁,因为最小化应用程序时不会调用
onDestroy()

如果图像在本地设备上(即与代码合并或来自用户图像库),然后,我可能会选择不让它们只是看不见或看不见,而只是从磁盘中动态地将它们带进来。事实证明,所有这些设备基本上都是基于闪存的,与主轴盘相比速度非常快。最有可能的情况是,用户无法感受到映像的磁盘IO性能受到的影响

通过这种方式,您还可以限制在任何时候存储在内存中的图像数量


我同意你也应该调查一下蒂姆的评估。

好吧。Android上的位图可能有点棘手。您能否提供有关位图来源及其大小的更好信息

否则,我建议调查以下事项:

  • 如果您正在加载远程图像,请签出。你也可以退房。我个人过去喜欢,但现在已经不再维护了

  • 如果您使用的是曾经是推荐选项的inPurgable标志,请尝试找到解决方法,因为它实际上会为每个图像分配更多内存

  • >P>如果你经常解码小的本地资产,考虑把你的草图保存在一个哈希表中,并在需要时重新使用它们。更少的GC

  • 如果您想对应用程序进行子类化,那么可以使用调用来了解您可能真正需要清理的时间(主要用于调试,而不是实际情况)。。。如果还不算太晚的话……:)

  • 看看克里斯·贝恩斯的博客。是一个非常有趣的内存缓存解决方案

  • 在需要和可能的时候,实现一个你调用的内存修剪器

  • 另一个不足为奇的优化是使用更小的对象时,你可以。。。考虑您的最小数据模型和图像大小,并尝试为它们提供一个一致的API

  • 对于Ben Max comment中的#3,我创建了两个有用的类:

    public abstract class SoftReferenceStorage<K, V>{
    private static HashMap<Object, SoftReference<Object>> objectsHash = new HashMap<Object, SoftReference<Object>>();
    
    @SuppressWarnings("unchecked")
    public V get(K key) {
        if (objectsHash.containsKey(key)) {
            SoftReference<Object> ref = objectsHash.get(key);
            if (ref.get() == null) {
                objectsHash.put(key, new SoftReference<Object>(createValueForKey(key)));
                return (V)objectsHash.get(key).get();
            } else {
                return (V)ref.get();
            }
        } else {
            objectsHash.put(key, new SoftReference<Object>(createValueForKey(key)));
            return (V)objectsHash.get(key).get();
        }
    }
    
    protected abstract V createValueForKey(K key);
    }
    

    嗯。。它们被加载到onCreate()中。我刚刚意识到,最小化它们根本不是问题。只有当我锁定屏幕时,应用程序似乎被破坏,或者至少调用了onDestroy(),当我多次锁定和解锁手机时,错误才会发生。。。有什么想法吗?你确定当你锁定手机时正在呼叫
    onDestroy()
    ?无论哪种方式,如果您只在
    onCreate()
    中创建它们,这都不重要。我唯一能想到的另一件事是打印日志,在每个位图上调用
    isRecycled()
    ,以确保它们确实被回收。
    public class FrequentlyUsedBitmapResources extends SoftReferenceStorage<Integer, Bitmap>{
    private static FrequentlyUsedBitmapResources instance = null;
    
    private Resources resources;
    
    public FrequentlyUsedBitmapResources(Resources resources) {
        super();
        this.resources = resources;
    }
    
    public static FrequentlyUsedBitmapResources getInstance() {
        if (instance == null) {
            instance = new FrequentlyUsedBitmapResources(HiDriveApp.getContext().getResources());
        }
        return instance;
    }
    
    @Override
    protected Bitmap createValueForKey(Integer resId) {
        return BitmapFactory.decodeResource(resources, resId);
    }
    }
    
    Bitmap b = FrequentlyUsedBitmapResources.getInstance().get(R.drawable.overview_photo_placeholder);