Android无法从内存中释放位图

Android无法从内存中释放位图,android,memory-management,bitmap,out-of-memory,Android,Memory Management,Bitmap,Out Of Memory,我在应用程序中处理位图时做了以下工作: LruCache用于位图,内存大小为1/8 使用BitmapFactory.Options计算inSampleSize 在创建位图时捕获OOM,在那里调用execall和System.gc() 还有位图的异步任务解码 我使用了位图工厂.decodeFile,看起来VM从内存中释放位图的速度不够快。我在某个地方读到,使用BitmapFactory.decodeFile可能有bug,所以我尝试使用BitmapFactory.decodeFileDescript

我在应用程序中处理位图时做了以下工作:

  • LruCache
    用于
    位图
    ,内存大小为1/8
  • 使用
    BitmapFactory.Options
    计算inSampleSize
  • 在创建
    位图时捕获
    OOM
    ,在那里调用
    execall
    System.gc()
  • 还有
    位图的
    异步任务
    解码
  • 我使用了
    位图工厂.decodeFile
    ,看起来VM从内存中释放
    位图的速度不够快。我在某个地方读到,使用
    BitmapFactory.decodeFile
    可能有bug,所以我尝试使用
    BitmapFactory.decodeFileDescriptor
    ,但在那里我随机得到以下信息:

    skia---解码器->解码返回false

    如果我不想使用
    BitmapFactory.decodeFileDescriptor
    或其他方法,那么这里需要修复
    FileInputStream
    是否有问题

    这花费了我太多的时间,我已经阅读了所有基于此的解决方案,以及谷歌如何建议
    位图
    处理,我已经走到了死胡同


    谢谢。

    使用大位图时总是有可能出现内存不足异常。。 所以,通过Android博客来处理

    并始终回收Bimap

    ImageView mImage;
    Drawable toRecycle = mImage.getDrawable();
            if ( toRecycle != null && toRecycle instanceof BitmapDrawable ) {
                if ( ( (BitmapDrawable) mImage.getDrawable() ).getBitmap() != null )
                    ( (BitmapDrawable) mImage.getDrawable() ).getBitmap().recycle();
            }
    
    gc()不会帮助您,也不能保证任何事情

    如果您完全确定不再需要逐出的位图,并且在任何地方都没有对它们的引用(否则将捕获“无法绘制回收的位图”异常),我建议您向LRU缓存添加逐出侦听器,并对每个逐出的值调用bitmap.recycle()

    不记得默认LRU缓存是否为设置逐出侦听器提供了方便的方法,但如果没有,则扩展它并添加所需的功能非常容易


    另外,我建议不要使用weakreference,因为您无法控制位图和LRU的用途。即使您加载了8个位图,这些位图非常适合您1/8的内存,但屏幕一次只能显示其中的4个(ImageView包含对位图的强烈引用),gc也会尽快清除剩余的4个位图。我的意思是超快。您必须为正在显示的每一新行(在ListView的情况下)重新加载位图。而屏幕外的每一个位图都必须重新加载。

    我在这里使用了
    软参考
    位图
    。现在,当快速滚动
    GridView
    绘制位图时,我可以看到GC一直在释放未使用的
    位图

    已测试设置my
    LruCache
    size完整内存大小,但仍然没有得到OOM


    使用此方法的惩罚不是很明显,考虑到我的
    GridView绘制的是非常自定义的图像,它的滚动非常平滑。

    您想对
    位图做什么?如果你问这个问题,我肯定你很怀疑你在listview或gridview中使用位图,这会导致OutOfMemoryError。如果是这种情况,你应该考虑Bitmaps的弱引用。你能在ListView和GridView中进一步阐述你的场景吗?全屏缩放请查看此链接我认为这可能会对你有所帮助。我们公司的政策不允许任何第三方库。这看起来很糟糕,当位图不在任何地方使用时,平台不应该自动回收该位图吗?而且我所有的位图都在LruCache中,所以我正在寻找一个更通用的答案,即位图回收发生在一个地方,而不是基于一个ImageView位图的单一解决方案。我可以覆盖LruCache上的entryRemoved,但我不知道如何100%保证检测位图不在某处使用,我可以调用recycle。所以WeakReference不是很好的选择吗,因为GC可能会检测到它是垃圾和空闲内存?为什么你认为GC跟不上,你得到OOM了吗?1/8是一个很小的内存量。你需要在短时间内加载大量位图,以使其溢出如此之多,以至于你得到一个OOMYes我确实得到OOM,也许我的LruCache位图的软引用可以让GC更难理解如何释放内存?好吧,这意味着带WeakReferences的列表是你最好的选择,在这种情况下使用LRU是没有意义的,因为位图是由引用控制的,而不是由LRU算法控制的。应该始终使用SoftReferences,否则gc仍然认为位图仍在使用,因为它的引用当前被内存中的某个对象持有。