使用滑动加载大尺寸图像时出现OutOfMemoryException

har*_*rry 4 android out-of-memory android-glide

所以,我一直在使用这个神奇的图书馆Glide在我的画廊应用程序中显示原生图像.我使用ViewPagerFragmentStatePagerAdapter展示全尺寸的图像.寻呼机的屏幕外限制是1(默认为保存存储器).我正在使用此代码将图像加载到ViewPager我的片段中:

Glide.with(getActivity())
     .loadFromMediaStore(uri)
     .asBitmap()
     .signature(new MediaStoreSignature(mimeType, dateModified, 
     .into(mImageView);
Run Code Online (Sandbox Code Playgroud)

现在,我在这里面临一些问题:

  1. 图像需要相当长的时间才能加载(如果没有缓存).因此,当用户滚动浏览器时,在加载图像时会显示空白屏幕,这是我想要避免的.有什么方法可以做到这一点吗?也许通过预先处理图像?
  2. 有时,在滚动大尺寸图像(主要是相机照片)时,会抛出OOM异常,并且由于没有加载图像,用户将留下空白屏幕.当我从potrait转为横向模式时,也会发生这种情况.所以,我试图用类似的方法atMost()-这降低图像的质量进一步的图像已经加载RGB_565并且approximate()这也是造成OOM.如何在不获得OOM异常的情况下实现最高图像质量?

对于第二个问题,我正在考虑为屏幕外项目加载质量较差的图像,然后在屏幕上显示时提高质量.可能吗?

我也试过使用ARGB_8888但结果是一样的:OOM异常.

TWi*_*Rob 22

TL; DR

  • 确保ImageView具有match_parent或固定dp为尺寸
    wrap_content使Glide加载全分辨率位图.
  • .placeholder() 在加载大位图时显示图像而不是空白空间
  • .thumbnail(float) 在较大的图像在后台加载时,快速加载下采样版本
  • 还要看看Glide问题,也许你会发现一些有用的东西.

细节

我很好奇xml是什么用的ImageView,因为我的猜测是wrap_content导致将图像以全分辨率加载到Bitmaps中(使用大量内存).如果是这种情况,我会建议使用match_parent或修复dp以降低分辨率.注意:您不会使用细节,因为目前无论如何都会在渲染时对图像进行下采样,只需将其向前移动到解码阶段.

您还必须确保您的应用程序没有内存使用限制.你可以在没有Glide的情况下将3张(屏幕外限制= 1表示1+current+1页面)相机照片加载到位图中吗?同样,假设这是全分辨率,应该可以在有或没有Glide的情况下在内存中存储3个屏幕大小的字节数,但是你必须引导Glide不以全分辨率加载.

您可以通过加载较小尺寸的图像.thumbnail(),它接受一个完全Glide.with...不包括.into() OR的速记参数,只是一个百分比(in 0.0 ... 1.0),首先尝试后者.它应该更快地解码图像,特别是对于像0.1这样的非常小的数字,然后当更高质量的图像完成时它被替换.

因此,更简单的选择是添加.thumbnail()到当前负载.更复杂的一个涉及.sizeMultiplier()Fragment创建视图的同时开始加载较低分辨率的图像,然后在ViewPager更改页面时开始加载高分辨率图像.这有助于窥视页面.

或者你可以使用一段.placeholder()时间图像加载所以它不是空的空间,而是"东西"那里.

关于使用ARGB_8888(每像素32位):如果你增加Bitmaps 消耗的内存(相比之下RGB_565(每像素16位),不要期望以后内存不足.一旦你使用565你可以尝试增加,但在那之前,这是徒劳的尝试.

还要看看Glide问题,也许你会发现一些有用的东西.