Android上的图像平铺,垃圾收集器速度变慢

Android上的图像平铺,垃圾收集器速度变慢,android,garbage-collection,Android,Garbage Collection,我正在实现一个需要大量大图像的应用程序,包括缩放、使用viewPager进行分页等等 使用整个图像不是一个选项,因为它会给出OutOfMemory异常,所以我正在实现一个自定义平铺系统。我已经在SD卡上把图像切成了几块,还有3个版本,低、中、高质量 其思想是根据缩放情况加载正确的分幅 理论上,这一切都很漂亮,而且这个系统在我们的iOS应用程序上已经运行得很好了,但是在Android上,由于垃圾收集器的存在,它变得慢得令人无法忍受 不知何故,垃圾收集器释放位图内存的时间似乎太长了,我的应用程序试图

我正在实现一个需要大量大图像的应用程序,包括缩放、使用viewPager进行分页等等

使用整个图像不是一个选项,因为它会给出OutOfMemory异常,所以我正在实现一个自定义平铺系统。我已经在SD卡上把图像切成了几块,还有3个版本,低、中、高质量

其思想是根据缩放情况加载正确的分幅

理论上,这一切都很漂亮,而且这个系统在我们的iOS应用程序上已经运行得很好了,但是在Android上,由于垃圾收集器的存在,它变得慢得令人无法忍受

不知何故,垃圾收集器释放位图内存的时间似乎太长了,我的应用程序试图在GC清除我要求他清除的位图之前创建新的位图,因此,如果用户分页太快,内存将增长,在某个时候,所有应用程序都会变慢,最终会在OOM上崩溃

每次用户转到下一页时,我都会在旧位图上调用以下内容:

lowResBitmap.recycle(); lowResBitmap=null

有没有更好的方法来处理Android上的位图分配和释放


编辑:我忘了在一些位图上调用.recycle(),现在它不再在OOM上崩溃,但速度非常慢(与我们的iOS应用程序相比),因为每次用户翻页时,Android都会多次调用GC,它会减慢我的绘图线程。

只要变量lowResBitmap是位图实例的唯一引用,那么是否在位图上调用recycle就不会有任何区别

从:

此(回收)是高级调用,通常不需要调用,因为 当没有更多内存时,正常GC进程将释放此内存 对该位图的引用

您是否测试过调用
System.gc()直接用于建议垃圾收集器在特定时间执行垃圾回收

更新(不幸的是,仅适用于API11+/Android 3:


可能你可以通过在加载新的磁贴时重新使用现有的位图来完全防止GC。我假设你所有的磁贴大小相同,因此这种方法是理想的。据我所知,这可以通过使用来实现。

你确定缓慢是因为GC吗?我怀疑你可能错了……做一些性能测试通过性能分析找出瓶颈所在。值得一提的是,我做了类似的基于磁贴的应用程序(磁贴为256x256.png)使用openGL渲染,它运行起来和iOS上的任何东西一样平滑。你是如何绘制屏幕的?你有多少线程?显示一些代码,我可能可以提供更好的帮助…奇怪的是,我禁用了高分辨率的瓷砖进行测试,当用户翻页时,我调用bitmap.recycle()页面上唯一的位图是lowRes版本。但是,看看DDMS,我看到很多GC_FOR_ALLOC和GC_CONCURRENT,即使我只处理一个位图。我有很多控制变量,但它们都是包含一些路径的小字符串,我不相信它们会导致GCOne更多的事情,我正在使用Pagination的ViewPager我仍然建议你做一些性能分析,看看瓶颈到底在哪里。这通常是一个令人惊讶和有启发性的练习。顺便说一句,为了帮助你的Ui线程保持100%的响应性,建议你以低于默认值的优先级运行辅助线程。没错。这非常简单。Tim Bray在.oh,lowResBitmap只是我如何释放的一个例子。我有一个HashMap保存着磁贴位图,我在该HashMap上迭代清除它们。当我内存不足时,我调用System.gc()。我不明白gc为什么有这么多事情要做。所需的收集时间主要取决于对象的数量。“大”图像使用的内存块应该很容易收集。可能内存碎片也是一个问题?顺便说一句:看看我更新的答案。嘿,位图重用非常酷!不幸的是,我必须支持2.2,所以我现在不能使用。但在不久的将来,我需要一个策略来维护两个版本,一个使用8级,另一个使用leve我11岁,所以我可以用这样的东西。谢谢!