我正在使用显示文本和图像的列表视图。我正在尝试使用 Task 对象异步下载图像并将它们加载到视图中以使列表视图有效滚动。但是我经常得到 OutOfMemoryExceptions,因为内存中有太多位图,即使我将它们保存到磁盘并访问它。我看到的一个原因是创建了许多任务(对于 20 个图像,创建了 20 个任务),它也可能占用内存。有没有一种有效的方法来做到这一点?
这是代码
我正在使用显示文本和图像的列表视图。我正在尝试使用 Task 对象异步下载图像并将它们加载到视图中以使列表视图有效滚动。但是我经常得到 OutOfMemoryExceptions,因为内存中有太多位图,即使我将它们保存到磁盘并访问它。我看到的一个原因是创建了许多任务(对于 20 个图像,创建了 20 个任务),它也可能占用内存。有没有一种有效的方法来做到这一点?
这是代码
您必须缩放位图,以使它们不会以全分辨率加载到内存中。100kb 大小的位图在内存中占 400kb,因为您需要为每个像素分配 4 个字节来保存 Alpha、Red、Green 和 Blue 的所有颜色值。如果您的图像是用相机拍摄的,它们的大小很容易达到 10 倍,并且很快就会占用大量内存。
我看到您将图像缩放,DecodeSampledBitmap
但是当您不再需要它时,您还需要处理它。
如果SetBitmap
您忘记处理您的位图,您可以简单地using
在它周围放置一条语句:
using(var bitmap = ImageDownloader.DownloadImage( url, width, height ))
{
if( !token.IsCancellationRequested )
(this.m_context as Activity).RunOnUiThread(
() => imageView.SetImageBitmap( bitmap )
);
}
另请查看Xamarin 文档中的有效加载大型位图文章。
除了有效地加载位图,我最近发现确保 Android 知道它可以稍后发布图像也很重要。
可用的解码选项之一是,如果您希望 Android 从内存中清除任何已加载的位图,则将InPurgeable
其设置为很重要。true
如果设置为 true,则生成的位图将分配其像素,以便在系统需要回收内存时可以清除它们。在这种情况下,当需要再次访问像素时(例如,绘制位图,调用 getPixels()),它们将被自动重新解码
看: