【问题标题】:Why can't I load a bitmap from an AsyncTask?为什么我不能从 AsyncTask 加载位图?
【发布时间】:2019-09-30 17:11:05
【问题描述】:

我正在尝试使用 AsyncTask 加载位图,以便在 UI 线程之外加载它们,因为它太慢了。 很遗憾,我在启动应用程序时遇到了问题。

AsyncTask 是在“BitmapBank”类中声明的类,用于处理应用程序的不同位图。我这样做是为了避免您无法从 Asynctask 返回某些内容。

这是我的代码:

    public Bitmap loadBitmap(Drawable drawable){
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        Canvas canvas = new Canvas(bitmap);
        drawable.draw(canvas);
        return bitmap;
    }

    private Bitmap scaleImage(Bitmap bitmap, int ratio){
        float widthHeightRatio = (float)(bitmap.getHeight())/(float)(bitmap.getWidth());
        int scaleHeight = (int)(widthHeightRatio * AppConstants.SCREEN_WIDTH/ratio);
        return Bitmap.createScaledBitmap(bitmap, AppConstants.SCREEN_WIDTH/ratio, scaleHeight, false);
    }

    private class BitmapTask extends AsyncTask<Drawable, Void, Void> {

        public BitmapTask(){
            super();
        }

        @Override
        protected Void doInBackground(Drawable... drawables) {
            rocket = prepareBitmap(drawables[0]);
            astronaut = prepareBitmap(drawables[1]);
            bloc = prepareBitmap(drawables[2]);
            background = prepareBitmap(drawables[3]);

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            rocket = scaleImage(rocket, 10);
            astronaut = scaleImage(astronaut, 20);
            bloc = scaleImage(bloc, AppConstants.NB_BLOCS);
            background = scaleImage(background, 1);
        }
    }

这里是日志:

Caused by: java.lang.OutOfMemoryError: Failed to allocate a 121701132 byte allocation with 16777216 free bytes and 86MB 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.example.myapplication.BitmapBank.prepareBitmap(BitmapBank.java:93)
        at com.example.myapplication.BitmapBank$BitmapTask.doInBackground(BitmapBank.java:117)
        at com.example.myapplication.BitmapBank$BitmapTask.doInBackground(BitmapBank.java:106)
        at android.os.AsyncTask$2.call(AsyncTask.java:295)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
        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)

谢谢你看看!

【问题讨论】:

  • 错误信息很清楚:您需要 ~121 MB 的图像,但只有 ~16 MB 可用。
  • 感谢您的回答,它来自哪里?仅在使用 asynctask 时出现...
  • @BigT 它不仅会在您使用 asynctask 时出现。这完全是因为您的堆内存不足以为其分配新的位图 -> 抛出内存不足异常。搜索“内存不足”和“堆” " 了解更多详情 :)
  • 感谢您的解释,实际上我是通过几个类传递appcontext,您认为内存泄漏可能来自那里吗?

标签: java android performance android-asynctask android-bitmap


【解决方案1】:

我建议您使用自动处理您的问题的“Glide”库。 Glide 是一个开源的 Android 库,用于加载动画图像、视频和 GIF。使用 Glide,您可以上传和显示来自许多不同来源的媒体,例如远程服务器或本地文件系统。

Glide.with(context)
    .load(new File(fileUri.getPath())) // Uri of the picture
    .into(profileAvatar);

【讨论】:

  • 非常感谢!如果我的图像是矢量,它可以工作吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
相关资源
最近更新 更多