Android Canvas尝试绘制太大的异常

时间:2018-07-09 07:29:11

标签: java android

我正在5种设备上测试我的应用程序:三星Galaxy Core,三星S6 edge,Moto G4,小米Redmi note 4和小米MiA1。加载位图在它们上工作正常,但在其他位上则抛出java.lang.RuntimeException: Canvas: trying to draw too large。您能帮我找到解决办法吗?

日志:

  

致命异常:java.lang.RuntimeException:画布:尝试绘制   太大(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)          在android.view.View.draw(View.java:20338)          在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)          在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)          在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)          在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)          在android.view.ViewGroup.drawChild(ViewGroup.java:4421)          在android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)          在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)          在android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692)          在android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800)          在android.view.ViewRootImpl.draw(ViewRootImpl.java:3447)          在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)          在android.os.Handler.handleCallback(Handler.java:789)          在android.os.Handler.dispatchMessage(Handler.java:98)          在android.os.Looper.loop(Looper.java:164)          在android.app.ActivityThread.main(ActivityThread.java:6938)          在java.lang.reflect.Method.invoke(Method.java)          在com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:327)          在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

4 个答案:

答案 0 :(得分:1)

尝试执行任何操作之前先压缩所选的图像。

这是压缩等高比图像的代码。

我将Uri转换为位图

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

我将位图,最大宽度,最小宽度传递给resize()。

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

resize()方法

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

答案 1 :(得分:1)

即使通过压缩来减小图像的文件大小,手机上显示的位图仍会占用大量内存。 Bitmap renders every pixel independently,因此是4048x3036 pixels image can take up to 48 Mb of memory

解决方案是在保持所需细节质量的同时降低分辨率。

Loading Large Bitmaps Efficiently

答案 2 :(得分:0)

您可以使用Picasso调整图片大小:

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

在调整大小方法中,这两个数字是图像的目标宽度和高度。随意更改它们(但不要输入太多数字!)。

对我有用。

答案 3 :(得分:0)

如果您的应用使用 Glide:

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