从Glide下载大图像时出现内存不足错误

时间:2018-04-18 08:36:48

标签: java android bitmap android-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)
        }

    });

我在onLfMemory错误的onLoad失败方法中大部分时间都结束了。

当我在设备文件浏览器中检查时,图像正在下载但第二次没有加载到图像视图中,第一次它适用于大图像。

我正在为第二次调用重复相同的代码。

以下是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$1.run(GlideExecutor.java:446)

您可以查看屏幕截图,其中显示图片已下载并存储在设备中。

enter image description here

4 个答案:

答案 0 :(得分:1)

在清单

中添加此内容
  android:largeHeap="true"

另外添加这是app.gradle

 dexOptions {// Prevent OutOfMemory with MultiDex during the build phase
        javaMaxHeapSize "4g"
    }

答案 1 :(得分:1)

尝试以下

Glide.with(context)
    .load(imgUrl)
    .thumbnail(0.1f)
    .into(imageView);

检查Referrence

答案 2 :(得分:1)

210 mb图像(o.O)太大而无法将其加载到内存中! 如果您的图像大小真的是210 MB,我认为最好的原因是通过使用httpConnection或像okhttp这样的库将图像从因特网下载为流到磁盘,然后将图像的缩小版本加载到内存中并显示给用户!

请参阅开发人员链接以高效加载大位图:

https://developer.android.com/topic/performance/graphics/load-bitmap.html#load-bitmap

如果要向用户显示整个图像,请使用此库:

https://github.com/davemorrissey/subsampling-scale-image-view

答案 3 :(得分:0)

自从我在提供所有解决方案之后发布了这个问题已有一段时间了,我正在发布一个对我有用的解决方案。

首先创建一个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)
        }

    });

非常感谢您提出的解决方案。