使用Glide加载大型图片时出现OutOfMemoryException异常

6

我一直在使用这个神奇的库Glide来在我的相册应用中显示本地图片。我使用了ViewPagerFragmentStatePagerAdapter来显示全尺寸的图片。为了节省内存,pager的离屏限制是1(默认值)。以下是我在fragment中将图像加载到ViewPager中的代码:

Glide.with(getActivity())
     .loadFromMediaStore(uri)
     .asBitmap()
     .signature(new MediaStoreSignature(mimeType, dateModified, 
     .into(mImageView);

现在,我遇到了一些问题,比如:
  1. 图片加载需要相当长的时间(如果不是缓存的话)。因此,在用户滚动viewpager时,会显示空白屏幕,而图像正在加载中,这正是我想要避免的。我能做什么来解决这个问题吗?也许通过预缓存图片?
  2. 有时,在滚动大尺寸图像(主要是相机照片)时,会抛出OOM异常,并且用户会看到空白屏幕,因为没有加载任何图像。当我从竖屏模式切换到横屏模式时,也会发生这种情况。所以,我尝试使用像atMost()这样的方法——进一步降低图像质量,因为图像已经以RGB_565的格式加载,而approximate()也会导致OOM。我怎样才能在不出现OOM异常的情况下获得最高的图像质量呢?

对于第二个问题,我想加载更低质量的图像用于离屏项目,然后在它们进入屏幕时提高质量。这可行吗?

我也尝试过使用ARGB_8888,但结果仍然是OOM异常。

1个回答

23

简述

  • 确保ImageView的尺寸为match_parent或固定的dp
    wrap_content会使Glide加载完整分辨率的位图。
  • .placeholder()在加载大位图时,显示图片而不是空白
  • .thumbnail(float)在后台加载更大的图像时,快速加载缩小版本
  • 同时查看Glide问题,也许会找到有用的信息。

详情

我很好奇ImageView的xml代码是什么,因为我的猜测是使用wrap_content会导致以完整分辨率加载到Bitmap中的图像(使用大量内存)。如果是这种情况,建议使用match_parent或固定的dp来降低分辨率。注意:您不会使用detail,因为当前该图像已经在渲染时进行了缩小,只需将其前置到解码阶段。

您还必须确保应用程序没有内存使用限制。如果没有使用Glide,您能否将3个摄像头照片(off screen limit = 1表示1+current+1)加载到位图中?再次假设这是完整分辨率,则应该可以使用或不使用Glide将3个屏幕大小的字节存储在内存中,但您必须指导Glide不要以完整分辨率加载。

您可以通过使用.thumbnail()来加载较小的图片,它接受一个完整的Glide.with...(不包括.into(),或者使用缩略图参数,该参数仅是一个百分比(在0.0 ... 1.0之间),建议先尝试后一种方法。这样可以更快地解码图片,特别是在数字很小(如0.1)时,等到更高质量的图片加载完成后再替换。
因此,更简单的选项是在当前的加载中添加.thumbnail()。更复杂的选项涉及在创建Fragment的视图时同时使用.sizeMultiplier()加载低分辨率图像,然后当ViewPager切换页面时开始加载高分辨率的图像。这有助于预览页面。
另外,您也可以在图片加载时使用.placeholder(),这样可以在图片加载时显示“某些东西”,而不是空白。
关于使用ARGB_8888(每像素32位):如果您增加了Bitmap的内存消耗(相对于RGB_565 (每像素16位),请勿期望后续内存不足。一旦您使用565成功,才尝试增加内存,否则会徒劳无功。

同时,可以查看Glide问题列表,或许会发现一些有用的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接