简体   繁体   English

Android Canvas 试图绘制过大的异常

[英]Android Canvas trying to draw too large Exception

I am testing my app on 5 devices: Samsung Galaxy core, Samsung S6 edge, Moto G4, Xiaomi Redmi note 4 and Xiaomi MiA1.我正在 5 台设备上测试我的应用程序:Samsung Galaxy core、Samsung S6 edge、Moto G4、Xiaomi Redmi note 4 和 Xiaomi MiA1。 Loading bitmaps works fine on them but on some other it throws java.lang.RuntimeException: Canvas: trying to draw too large .加载位图在它们上工作正常,但在其他一些上它会抛出java.lang.RuntimeException: Canvas: trying to draw too large Can you help me find a solution?你能帮我找到解决办法吗?

Log:日志:

Fatal Exception: java.lang.RuntimeException: Canvas: trying to draw too large(135788800bytes) bitmap.致命异常:java.lang.RuntimeException:Canvas:试图绘制太大(135788800bytes)位图。 at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:229) at android.view.RecordingCanvas.drawBitmap(RecordingCanvas.java:97) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529) at 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) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java:20341) at android.view.View.updateDisplayListIfDirty(View.java:19283) at 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.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.d在 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) at 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) at 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) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java:20341) at com.android.internal.policy.DecorView.draw(DecorView.java:979) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686) at android.view.ThreadedRenderer.updateR 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) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2769) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1738) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7745) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) at android.view.Choreographer.doCallbacks(Choreographer.java:723) at android.view.Choreographer.doFrame(Choreographer.java:658) at 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 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) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) id.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Try to compress your selected image before doing any action.在执行任何操作之前尝试压缩您选择的图像。

Here is the code that compress image with equal aspect ratio.这是以相等的纵横比压缩图像的代码。

I converted Uri to bitmap我将 Uri 转换为位图

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

The i pass the bitmap, maxwidth, minWidth to resize().我将位图、maxwidth、minWidth 传递给 resize()。

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

resize() method调整大小()方法

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

Even if you reduce the file size of your image by compressing it, the Bitmap shown on the phone will still take substantial amount of memory.即使您通过压缩来减小图像的文件大小,手机上显示的位图仍然会占用大量内存。 Bitmap renders every pixel independently and therefore a 4048x3036 pixels image can take up to 48 Mb of memory位图独立渲染每个像素,因此4048x3036 像素的图像最多可能占用 48 Mb 的内存

The solution would be to reduce the resolution while maintaining desirable detail quality.解决方案是降低分辨率,同时保持理想的细节质量。

Loading Large Bitmaps Efficiently 高效加载大型位图

You can use Picasso to resize your image:您可以使用 Picasso 调整图像大小:

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

In resize method, the 2 numbers are the target width and height of your image.在调整大小方法中,2 个数字是图像的目标宽度和高度。 Change them as you like (but don't put too large numbers!).随意更改它们(但不要输入太大的数字!)。

It worked for me.它对我有用。

如果您的应用使用 Glide:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM