从 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);

勾选Referrence

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)
        }

    });

感谢大家提出的解决方案。