问题描述
因此,我一直在使用这个令人惊叹的库 Glide 在我的图库应用中显示本机图像.我正在使用ViewPager
和FragmentStatePagerAdapter
来显示完整尺寸的图像.传呼机的屏幕外限制为1
(默认设置为节省内存).我正在使用此代码将图像加载到片段中的ViewPager
中:
So, I have been using this amazing library Glide for showing native images in my gallery app. I am using ViewPager
with FragmentStatePagerAdapter
to show full size images. The pager's off screen limit is 1
(default to save memory). I am using this code to load images into ViewPager
in my fragment:
Glide.with(getActivity())
.loadFromMediaStore(uri)
.asBitmap()
.signature(new MediaStoreSignature(mimeType, dateModified,
.into(mImageView);
现在,我在这里遇到了一些问题,例如:
Now, I am facing some issues here like:
- 加载图像需要花费相当长的时间(如果未缓存).因此,当用户滚动浏览viewpager时,在加载图像时会显示空白屏幕,这是我要避免的事情.有什么办法可以做到吗?也许是通过预缓存图像?
- 有时,在滚动查看大尺寸图像(主要是相机照片)时,会抛出 OOM异常,并且由于未加载任何图像,因此用户处于空白屏幕.当我从potrait切换到风景模式时,也会发生这种情况.因此,我尝试使用
atMost()
之类的方法-由于图像已经加载到RGB_565
和approximate()
中,这进一步降低了图像质量,这也导致了OOM.如何在没有OOM异常的情况下获得最高的图像质量?
- Images take quite some amount of time to load (if not cached). So, while user is scrolling through the viewpager blank screen is shown while image is loading which is what I want to avoid. Is there any way I can do this? Maybe by precaching images?
- Sometimes, while scrolling through large size images (mainly Camera photos) OOM Exception is thrown and user is left with blank screen as no image is loaded. This also happens when I am shifting from potrait to landscape mode. So, I tried to use methods like
atMost()
-- which degrade the quality of image further as images are already loaded inRGB_565
andapproximate()
which is also causing OOM. How can I achieve maximum image quality without getting OOM exceptions?
对于第二个问题,我正在考虑为屏幕外的项目加载质量较低的图像,然后在屏幕上出现图像时提高质量.有可能吗?
For the second issue, I was thinking to load lesser quality images for the off screen items and then enhance quality when they come on-screen. Is it possible?
我也尝试使用ARGB_8888
,但是结果是一样的:OOM异常.
I have also tried to use ARGB_8888
but the result was same: OOM exception.
推荐答案
TL; DR
- 确保
ImageView
具有match_parent
或固定的dp
作为尺寸wrap_content
使Glide加载全分辨率位图. -
.placeholder()
在加载大位图时显示图像而不是空白空间 -
.thumbnail(float)
快速加载降采样的版本,而背景中加载较大的图像 - 也环顾四周滑翔问题,也许您会找到有用的东西.
- Make sure the
ImageView
hasmatch_parent
or fixeddp
as dimensionswrap_content
makes Glide load full resolution Bitmaps. .placeholder()
shows an image instead of empty space while loading large bitmap.thumbnail(float)
loads a downsampled version fast while the bigger image is loading in the background- Also look around the Glide issues, maybe you find something helpful.
TL;DR
我想知道ImageView
的xml是什么,因为我猜是wrap_content
导致将全分辨率的图像加载到Bitmap
中(使用大量内存).如果是这种情况,我建议使用match_parent
或固定的dp
降低分辨率.注意:您不会使用细节,因为当前无论如何在渲染时都会对图像进行降采样,只需将其拉到解码阶段即可.
I would be curious what the xml is for the ImageView
, because my guess is it's wrap_content
which results in loading images at full resolution into Bitmap
s (using a lot of memory). If that's the case I would suggest using match_parent
or fixed dp
to lower the resolution. Note: you won't use detail, because currently the image is downsampled at render time anyway, just pulling that forward to decoding phase.
您还必须确保您的应用程序没有内存使用限制.您是否可以加载3(屏幕限制= 1是指将1+current+1
页)相机照片转换为不带Glide的位图?同样,假设这是全分辨率,则无论有没有Glide,都应该有可能在内存中存储3个屏幕大小的字节,但是您必须指导Glide不要以全分辨率加载.
You also have to make sure that your app doesn't have constraints for memory usage. Can you load 3 (off screen limit = 1 means 1+current+1
pages) camera photos into Bitmaps without Glide? Again, assuming this is full resolution, it should be possible to store 3 screen size amount of bytes in memory with or without Glide, but you have to guide Glide to not load at full resolution.
您可以通过.thumbnail()
加载较小尺寸的图像,它接受完整的Glide.with...
不包括.into()
,或者有速记参数只是一个百分比(在0.0 ... 1.0
中),请先尝试使用后者.它应该能够更快地解码图像,尤其是使用0.1这样的很小的数字时,然后在质量更高的图像完成后就将其替换.
You can load smaller sized image via .thumbnail()
, it accepts a full Glide.with...
not including .into()
OR there's a shorthand parameter which is just a percentage (in 0.0 ... 1.0
), try the latter first. It should decode the image much faster, especially with a really small number like 0.1 and then when higher quality one finishes it's replaced.
因此,更简单的选择是将.thumbnail()
添加到当前负载中.一个更令人费解的问题涉及使用 .sizeMultiplier()
同时创建Fragment
的视图,然后在ViewPager
更改页面后开始加载高分辨率的视图.这有助于窥视页面.
So the simpler option is to add .thumbnail()
to your current load. A more convoluted one involves to start loading a lower resolution image with .sizeMultiplier()
at the same time the Fragment
's view is created and then start loading the high resolution one when the ViewPager
has changed page. This helps with peeking the pages.
或者,您可以只使用 .placeholder()
,当图像正在加载时,它不是空白空间,而是东西".
Alternatively you can just use a .placeholder()
while the image is loading so it's not empty space, but "something" there.
关于使用ARGB_8888
(每像素32位):如果将内存消耗增加了Bitmap
s(与RGB_565
(每像素16位)相比),则不要期望以后会耗尽内存.一旦将其与565配合使用,您可以尝试增加,但在那之前尝试是徒劳的.
Regarding using ARGB_8888
(32 bit per pixel): if you increase the memory consumed by Bitmap
s (compared to RGB_565
(16 bit per pixel) don't expect to get run out of memory later. Once you get it working with 565 you can try increasing, but until then it's futile trying.
还要环顾滑翔机问题,也许您会找到有用的东西.
Also look around the Glide issues, maybe you find something helpful.
这篇关于使用glide加载大尺寸图像时出现OutOfMemoryException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!