簡體   English   中英

Android Canvas 試圖繪制過大的異常

[英]Android Canvas trying to draw too large Exception

我正在 5 台設備上測試我的應用程序:Samsung Galaxy core、Samsung S6 edge、Moto G4、Xiaomi Redmi note 4 和 Xiaomi MiA1。 加載位圖在它們上工作正常,但在其他一些上它會拋出java.lang.RuntimeException: Canvas: trying to draw too large 你能幫我找到解決辦法嗎?

日志:

致命異常:java.lang.RuntimeException:Canvas:試圖繪制太大(135788800bytes)位圖。 在 android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:229) 在 android.view.RecordingCanvas.drawBitmap(RecordingCanvas.java:97) 在 android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529) 在 android。 widget.ImageView.onDraw(ImageView.java:1367) at android.view.View.draw(View.java:20338) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.View.draw (View.java:20061) 在 android.view.ViewGroup.drawChild(ViewGroup.java:4421) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) 在 android.view.View.draw(View.java: 20341) 在 android.view.View.updateDisplayListIfDirty(View.java:19283) 在 android.view.View.draw(View.java:20061) 在 android.view.ViewGroup.drawChild(ViewGroup.java:4421) 在 android。 view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild (ViewGroup.java:4421) 在 android.view.ViewGroup.d ispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java) :4421) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) 在 android.view.View.updateDisplayListIfDirty(View.java:19274) 在 android.view.View.draw(View.java:20061) 在 android .view.ViewGroup.drawChild(ViewGroup.java:4421) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) 在 android.view.View.updateDisplayListIfDirty(View.java:19274) 在 android.view.View。 draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java) :20341) 在 com.android.internal.policy.DecorView.draw(DecorView.java:979) 在 android.view.View.updateDisplayListIfDirty(View.java:19283) 在 android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:第686章) ootDisplayList(ThreadedRenderer.java:692) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3447) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java) :3234) 在 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2769) 在 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1738) 在 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7745)在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) 在 android.view.Choreographer.doCallbacks(Choreographer.java:723) 在 android.view.Choreographer.doFrame(Choreographer.java:658) 在 android。 view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper .loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Method.java) at com.andro id.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

在執行任何操作之前嘗試壓縮您選擇的圖像。

這是以相等的縱橫比壓縮圖像的代碼。

我將 Uri 轉換為位圖

bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

我將位圖、maxwidth、minWidth 傳遞給 resize()。

resizeBitmap = resize(bitmap, bitmap.getWidth() / 2, bitmap.getHeight() / 2);

調整大小()方法

private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
    if (maxHeight > 0 && maxWidth > 0) {
        int width = image.getWidth();
        int height = image.getHeight();
        float ratioBitmap = (float) width / (float) height;
        float ratioMax = (float) maxWidth / (float) maxHeight;

        int finalWidth = maxWidth;
        int finalHeight = maxHeight;
        if (ratioMax > ratioBitmap) {
            finalWidth = (int) ((float) maxHeight * ratioBitmap);
        } else {
            finalHeight = (int) ((float) maxWidth / ratioBitmap);
        }
        image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
        return image;
    } else {
        return image;
    }
}

即使您通過壓縮來減小圖像的文件大小,手機上顯示的位圖仍然會占用大量內存。 位圖獨立渲染每個像素,因此4048x3036 像素的圖像最多可能占用 48 Mb 的內存

解決方案是降低分辨率,同時保持理想的細節質量。

高效加載大型位圖

您可以使用 Picasso 調整圖像大小:

Picasso.get().load(imageUri).resize(512,512).into(imageView);

在調整大小方法中,2 個數字是圖像的目標寬度和高度。 隨意更改它們(但不要輸入太大的數字!)。

它對我有用。

如果您的應用使用 Glide:

Glide.with(context).load(uri).into(imageView);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM