从 Glide 下载大图像时出现内存不足错误
Out of Memory Error when downloading a large image from Glide
这是我尝试下载大图片的代码..
RequestOptions requestOptions = new RequestOptions();
requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL);
requestOptions.skipMemoryCache(true);
Glide.with(this)
.load(rogImage)
.apply(requestOptions)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
ProgressBarHandler.unloadProgressScreen(getActivity());
return false;
}
})
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
tempImageView.setImageDrawable(resource)
}
});
我大部分时间都在 onLoad 方法失败并出现 OutOfMemoryError。
当我在 设备文件资源管理器 中检查时,图像正在下载但第二次没有加载到图像视图中,第一次它非常适合大图像。
我正在为第二次调用重复相同的代码。
下面是 android studio 中给出的实际错误信息。
Glide: Root cause (1 of 13)
java.lang.OutOfMemoryError: Failed to allocate a 210639956 byte allocation with 16777216 free bytes and 197MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:975)
at android.graphics.Bitmap.createBitmap(Bitmap.java:946)
at android.graphics.Bitmap.createBitmap(Bitmap.java:913)
at com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool.createBitmap(LruBitmapPool.java:149)
at com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool.getDirty(LruBitmapPool.java:142)
at com.bumptech.glide.load.resource.bitmap.Downsampler.setInBitmap(Downsampler.java:688)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeFromWrappedStreams(Downsampler.java:297)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:207)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:160)
at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:33)
at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:16)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:72)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:55)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:45)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:58)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:43)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:498)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:469)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:455)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:407)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:376)
at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:95)
at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:74)
at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:75)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:299)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:266)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory.run(GlideExecutor.java:446)
您可以查看显示图像已下载并存储在设备中的屏幕截图。
在清单中添加这个
android:largeHeap="true"
另外加上这个是app.gradle
dexOptions {// Prevent OutOfMemory with MultiDex during the build phase
javaMaxHeapSize "4g"
}
试试下面
Glide.with(context)
.load(imgUrl)
.thumbnail(0.1f)
.into(imageView);
210 MB 图像 (o.O) 太大,无法将其加载到内存中!
如果您的图像大小真的是 210 mb,我认为最好的原因是使用 httpConnection 或像 okhttp 这样的库将图像作为流从互联网下载到磁盘,而不是将图像的缩小版本加载到内存中并将其显示给用户!
请参阅开发人员 link 以高效加载大型位图:
https://developer.android.com/topic/performance/graphics/load-bitmap.html#load-bitmap
如果您想向用户显示整个图像,请使用此库:
https://github.com/davemorrissey/subsampling-scale-image-view
自从我在完成所有提供的解决方案后发布这个问题以来已经有一段时间了,我发布了一个对我有用的解决方案。
首先创建了一个单独的 glide 实例并在整个应用程序中使用它
mainFragment.getmGlide().with(mainFragment.getMcurrentContext())
接下来添加了请求选项来限制图像的高度和宽度,从而大大减少了内存使用量。
RequestOptions requestOptions = new RequestOptions();
requestOptions.dontAnimate();
requestOptions.diskCacheStrategy(DiskCacheStrategy.RESOURCE);
requestOptions.timeout(10000);
requestOptions.override(2000,2000);
requestOptions.fitCenter();
requestOptions.format(DecodeFormat.PREFER_RGB_565);
mainFragment.getmGlide().with(mainFragment.getMcurrentContext())
.asBitmap()
.load(rogImage)
.apply(requestOptions)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
ProgressBarHandler.unloadProgressScreen(getActivity());
return false;
}
})
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
tempImageView.setImageDrawable(resource)
}
});
感谢大家提出的解决方案。
这是我尝试下载大图片的代码..
RequestOptions requestOptions = new RequestOptions();
requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL);
requestOptions.skipMemoryCache(true);
Glide.with(this)
.load(rogImage)
.apply(requestOptions)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
ProgressBarHandler.unloadProgressScreen(getActivity());
return false;
}
})
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
tempImageView.setImageDrawable(resource)
}
});
我大部分时间都在 onLoad 方法失败并出现 OutOfMemoryError。
当我在 设备文件资源管理器 中检查时,图像正在下载但第二次没有加载到图像视图中,第一次它非常适合大图像。
我正在为第二次调用重复相同的代码。
下面是 android studio 中给出的实际错误信息。
Glide: Root cause (1 of 13)
java.lang.OutOfMemoryError: Failed to allocate a 210639956 byte allocation with 16777216 free bytes and 197MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:975)
at android.graphics.Bitmap.createBitmap(Bitmap.java:946)
at android.graphics.Bitmap.createBitmap(Bitmap.java:913)
at com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool.createBitmap(LruBitmapPool.java:149)
at com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool.getDirty(LruBitmapPool.java:142)
at com.bumptech.glide.load.resource.bitmap.Downsampler.setInBitmap(Downsampler.java:688)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeFromWrappedStreams(Downsampler.java:297)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:207)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:160)
at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:33)
at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:16)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:72)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:55)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:45)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:58)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:43)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:498)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:469)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:455)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:407)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:376)
at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:95)
at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:74)
at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:75)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:299)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:266)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory.run(GlideExecutor.java:446)
您可以查看显示图像已下载并存储在设备中的屏幕截图。
在清单中添加这个
android:largeHeap="true"
另外加上这个是app.gradle
dexOptions {// Prevent OutOfMemory with MultiDex during the build phase
javaMaxHeapSize "4g"
}
试试下面
Glide.with(context)
.load(imgUrl)
.thumbnail(0.1f)
.into(imageView);
210 MB 图像 (o.O) 太大,无法将其加载到内存中! 如果您的图像大小真的是 210 mb,我认为最好的原因是使用 httpConnection 或像 okhttp 这样的库将图像作为流从互联网下载到磁盘,而不是将图像的缩小版本加载到内存中并将其显示给用户!
请参阅开发人员 link 以高效加载大型位图:
https://developer.android.com/topic/performance/graphics/load-bitmap.html#load-bitmap
如果您想向用户显示整个图像,请使用此库:
https://github.com/davemorrissey/subsampling-scale-image-view
自从我在完成所有提供的解决方案后发布这个问题以来已经有一段时间了,我发布了一个对我有用的解决方案。
首先创建了一个单独的 glide 实例并在整个应用程序中使用它
mainFragment.getmGlide().with(mainFragment.getMcurrentContext())
接下来添加了请求选项来限制图像的高度和宽度,从而大大减少了内存使用量。
RequestOptions requestOptions = new RequestOptions();
requestOptions.dontAnimate();
requestOptions.diskCacheStrategy(DiskCacheStrategy.RESOURCE);
requestOptions.timeout(10000);
requestOptions.override(2000,2000);
requestOptions.fitCenter();
requestOptions.format(DecodeFormat.PREFER_RGB_565);
mainFragment.getmGlide().with(mainFragment.getMcurrentContext())
.asBitmap()
.load(rogImage)
.apply(requestOptions)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
ProgressBarHandler.unloadProgressScreen(getActivity());
return false;
}
})
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
tempImageView.setImageDrawable(resource)
}
});
感谢大家提出的解决方案。