Android 加载位图的最快方法,创建后重新使用位图

Android 加载位图的最快方法,创建后重新使用位图,android,bitmap,java-native-interface,Android,Bitmap,Java Native Interface,我有一个生成许多位图对象的应用程序。创建位图后,所有剩余位图的大小都将相同 目前,我可以在手机上以大约50-80毫秒的时间加载/创建一个新位图,满足我的需要。然而,由于创建这些文件的速度很快,我遇到了持续的GC 我想重新使用相同的位图对象,但不确定如何通过sdk实现这一点 我确实编译了libjpeg,并通过NDK加载了我的图像,重新使用了我的位图,但是我的加载速度下降到了200毫秒左右,这太慢了。 当我有代码在我面前时,我会稍后发布代码 问题: 有没有办法重复使用位图对象以避免GC? 有没有更快

我有一个生成许多位图对象的应用程序。创建位图后,所有剩余位图的大小都将相同

目前,我可以在手机上以大约50-80毫秒的时间加载/创建一个新位图,满足我的需要。然而,由于创建这些文件的速度很快,我遇到了持续的GC

我想重新使用相同的位图对象,但不确定如何通过sdk实现这一点

我确实编译了libjpeg,并通过NDK加载了我的图像,重新使用了我的位图,但是我的加载速度下降到了200毫秒左右,这太慢了。 当我有代码在我面前时,我会稍后发布代码

问题:

有没有办法重复使用位图对象以避免GC? 有没有更快的方法通过NDK加载我的图像?是否可以连接到操作系统加载位图的方式?我知道libjpegTurbo,但我目前无法编译它(另一天的另一个主题)


关于最好的方法还有其他想法吗。

为什么不使用hashmap来存储位图呢?然后在加载位图时,首先检查它是否在hashmap中,如果是,您可以重用它。如果它不在hashmap中,请正常保存,然后将其插入hashmap。

我建议使用IntBuffer,其中包含需要交换的像素数据。然后,创建一个所需大小的位图,当需要交换像素时,使用bitmap.copyPixelsFromBuffer()。我想这比每次需要更改像素数据时分配/取消分配位图内存要快得多。如果希望将缓冲区保存在内存中以便快速检索,那么最好将缓冲区保存在hashmap中


也可以选择将setPixels()与int数组一起使用。copyPixelsFromBuffer()的好处在于,没有尝试像素转换,而且选项更少,因此速度可能会更快。

我每秒创建大约20个位图,因此无法将它们全部保存在内存中。实际上,我有一个后台线程填充一个队列,我从中提取新位图。最大的问题是在我的后台线程中,我不想创建新的位图对象,而是想从位图池中提取并重新使用它们,这样我就不必有那么多GC。@broschb如果无法将它们保存在内存中,那么如何重新使用它们?你知道这没有道理,对吧?如果您有内存限制,那么最好的办法是使用hashmap和队列实现图像缓存,然后在加载的位图数量达到一定限制后,从队列中删除较旧的位图,并提示GC应将其从内存中清除。hashmap将用于标识位图当前是否在队列中及其位置。我可以通过更改位图的像素数据,使用另一个位图的新像素数据重新使用位图。请参阅@Samuels response,我想这是我一直在思考的问题。@broschb位图或int数组中的每个像素都会占用4字节的内存。这意味着一个700x400整数数组已经占用了约273千字节。我非常怀疑位图对象占用的内存超过1千字节,最多2千字节。如果你能在内存中保存所有int数组,你几乎肯定能保存所有位图对象。int数组是位图对象的绝大多数,因此如果您不实现任何缓存,我怀疑它会解决GC问题。@onit 700x400位图应该占用大约1.1MB。我喜欢int缓冲区的想法,但我看到的唯一显著的好处可能是内存空间。最快的方法是将对象保存在内存中,在这种情况下,只有当int缓冲区明显小于位图对象时,这才是一个显著的改进。我对此表示怀疑,除非位图相对较小。像素数据来自哪里?它在某个点上一定是一个int数组,对吗?因此,如果每次分配一个位图,那么就有内存用于int数组,内存用于位图。假设您已经完成了int数组的处理,那么这是一个需要进行垃圾收集的对象。然后,在处理完位图后,还需要对其进行垃圾收集。这是两个需要垃圾收集的大对象。如果只使用一个位图,则不会有需要进行垃圾收集的额外对象。位图GC需要更长的时间,因为它也有JNI调用。如果您在内存中重用位图,GC不再是一个大问题,除非您有大量无法缓存在内存中的图像(我个人在较新的手机上在内存中存储了数百个位图)。我认为位图使用的内存中至少有95%是实际的底层int数组,除非位图非常小。如果他能将位图缓存在内存中(这将是最大的性能提升),我怀疑这将是一个显著的性能提升。如果他需要不断地回收位图,我同意这将是一个进步。谢谢你的想法,我将研究其中一些。我正在处理的图像大约是700x400,在我开始处理问题之前,我可以在内存中获得大约8-10个。我以前有一个在位图上重复使用(替换像素数据)的实现,这大大减少了GC,但我在我的应用程序中遇到了其他的实现。方法,并且不得不开始加载图像。@Samuel和onit,感谢您的帮助和建议。考虑到这一点,我们希望使用IntBuffers方法运行一些测试。如何将图像直接加载到IntBuffers中?我能看到的唯一方法是加载位图,获取像素并加载到intBuffer中,但我确信我缺少一个明显的方法来实现这一点。