【解决】trying to draw too large(147456000bytes) bitmap

异常信息

FATAL EXCEPTION: main
Process: com.sdt.sdtas, PID: 8695
java.lang.RuntimeException: Canvas: trying to draw too large(147456000bytes) bitmap.
at android.graphics.RecordingCanvas.throwIfCannotDraw(RecordingCanvas.java:266)
at android.graphics.BaseRecordingCanvas.drawBitmap(BaseRecordingCanvas.java:94)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:549)
at android.view.View.getDrawableRenderNode(View.java:23008)
at android.view.View.drawBackground(View.java:22937)
at android.view.View.draw(View.java:22711)
at android.view.View.updateDisplayListIfDirty(View.java:21594)
at android.view.View.draw(View.java:22450)
at android.view.ViewGroup.drawChild(ViewGroup.java:4528)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4289)
at android.view.View.updateDisplayListIfDirty(View.java:21585)
at android.view.View.draw(View.java:22450)
at android.view.ViewGroup.drawChild(ViewGroup.java:4528)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4289)
at android.view.View.updateDisplayListIfDirty(View.java:21585)
at android.view.View.draw(View.java:22450)
at android.view.ViewGroup.drawChild(ViewGroup.java:4528)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4289)
at android.view.View.draw(View.java:22722)
at com.android.internal.policy.DecorView.draw(DecorView.java:837)
at android.view.View.updateDisplayListIfDirty(View.java:21594)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:534)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:540)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:616)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4530)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4250)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3373)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2178)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8808)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1037)
at android.view.Choreographer.doCallbacks(Choreographer.java:845)
at android.view.Choreographer.doFrame(Choreographer.java:780)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7870)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

异常原因

以Bitmap默认采用的色彩模式Bitmap.Config.ARGB_8888为例;在该模式中一共有四个通道,其中A表示Alpha,R表示Red,G表示Green,B表示Blue;并且这四个通道每个各占8位即一个字节,所以合起来共计4个字节。

即 bitmap占用内存 = width x height x 4

查看源码可知安卓系统默认对图片的大小限制是100M

android/graphics/BaseRecordingCanvas.java

public static final int MAX_BITMAP_SIZE = getPanelFrameSize();

private static int getPanelFrameSize() {
    final int DefaultSize = 100 * 1024 * 1024; // 100 MB;
    return Math.max(SystemProperties.getInt("ro.hwui.max_texture_allocation_size", DefaultSize),
            DefaultSize);
}

@Override
protected void throwIfCannotDraw(Bitmap bitmap) {
    super.throwIfCannotDraw(bitmap);
    int bitmapSize = bitmap.getByteCount();
    if (bitmapSize > MAX_BITMAP_SIZE) {
        throw new RuntimeException(
                "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
    }
}

解决方法

  1. 直接将工程中的大图,参考上述计算方式进行适当缩小。
  2. 如果发现工程中没有特别大的图片,可能是因为资源图放到了低分辨率的drawable中如drawable-mdpi,可以尝试将大图放到xxhdpi或者nodpi中。
提供的引用中未提及在Android Studio中解决“Canvas trying to draw too large bitmap”问题的解决方案,不过可以根据一般的经验给出一些常见的解决办法。 ### 缩放位图 在将位图绘制到Canvas之前,将其缩放到合适的大小。可以使用`BitmapFactory.Options`来进行缩放。 ```java BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; // 设置采样率,这里设置为2表示缩小为原来的1/2 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options); ``` ### 分块绘制 如果位图过大无法一次性绘制,可以将其分成多个小块,然后逐块绘制到Canvas上。 ```java int blockWidth = 100; int blockHeight = 100; for (int x = 0; x < bitmap.getWidth(); x += blockWidth) { for (int y = 0; y < bitmap.getHeight(); y += blockHeight) { int width = Math.min(blockWidth, bitmap.getWidth() - x); int height = Math.min(blockHeight, bitmap.getHeight() - y); Bitmap block = Bitmap.createBitmap(bitmap, x, y, width, height); canvas.drawBitmap(block, x, y, null); } } ``` ### 释放不再使用的资源 及时释放不再使用的位图资源,避免内存占用过高。 ```java if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); bitmap = null; } ``` ### 检查设备内存状态 在绘制之前检查设备的内存状态,如果内存不足,可以采取相应的措施,如减少绘制的内容或提示用户清理内存。 ```java ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); activityManager.getMemoryInfo(memoryInfo); if (memoryInfo.lowMemory) { // 内存不足,采取相应措施 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值