Share via


WP8下解决加载图片所导致的内存不够问题的一些建议

由于Windows Phone 8设备的物理内存有限, SDK中限制了应用程序的最大可用内存。对于普通XAML 应用程序来说,512MB内存的设备提供给应用的最大内存是150MB,1GB或以上内存的设备提供给应用的最大内存是300MB. 即使在Menifest文件中提供了ID_FUNCCAP_EXTEND_MEM选项,也只是将512MB内存的设备的最大可用内存提高到180MB。在这么点内存中如果要加载大量图片就很容易出现内存不足的问题。这里我就如何解决加载图片所导致的内存不够问题提供一些建议:

1.       尽量避免加载不必要的高分辨率的图片。即使这个图片是JPG或PNG的格式,内部在渲染的时候还是需要解码为位图格式,所以仍然需要占用和分辨率相对应的大小的内存,比如说,一张图片分别1280×768的JPG图片可能只有几百K甚至几十K大小,但是如果将它解码到内存中,那就会占用固定的4MB(1280x768x4)左右的内存。如果图片过大的话,我们可以通过设定DecodePixelWidth/DecodePixelHeight来减少解码图像的大小,但是如果可能的话,最好的办法还是让服务端提供合适分辨率的图片。

2.       对于ImageOpened/ImageFailed等事件的处理函数,要记得及时释放。.NET应用很容易犯一个普遍的内存泄露问题,WP8应用也会有同样的问题:如果声明事件的那个对象生命周期长于处理函数所在的对象就会发生内存泄漏。所以对于这一类事件处理函数,您需要及时释放。 具体对这一类内存泄露的分析你可以参看以下链接:https://blogs.msdn.com/b/abhinaba/archive/2009/05/05/memory-leak-via-event-handlers.aspx

3.       在需要释放图片资源的时候将图片的UriSource设置为null。由于Window Phone内部对图片有基于Uri的缓存机制,如果你不将UriSource设为null,那么相应的缓存就得不到释放,这样的话跟内存泄露也没多大区别了。

4.       调用SetSource将图片Source设置为一个零字节的数组{0}来强制释放图片内存。由于图像数据都是分配在native端,在Manage端图片对象只有几十个字节,所以系统的垃圾回收机制通常不会及时回收数量这么小的内存。通过这种方式可以强制将图像内存卸载。

5.       在图片打开成功或失败之前不要尝试再加载图片,比如说再次设置UriSource或者调用SetSource。不管图片的加载是成功还是失败,你都必须等待图片加载完成之后再改变数据源。

6.       避免在一段代码中频繁的加载和卸载图片,比如说,在一个for循环语句中不停的加载和卸载图片来获取图片的某些信息。这种情况下系统的垃圾回收没有机会来将不用的图像内存释放掉。如果你的代码逻辑需要你这么做,你可以将每个图片加载卸载的操作都放在单独的一个Dispatcher工作项中完成。

这些都是WP8上应用程序加载图片导致内存不够的常见问题,希望能对你的开发有所帮助。