在Canvas上绘制Bitmap时触发NullPointerException问题求助
我之前也碰到过一模一样的问题,这个空指针的根源其实很明确——你的android_guy Bitmap对象是null,具体来说是BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher)这一步返回了null,导致后续调用createScaledBitmap也拿不到有效的Bitmap,最后执行canvas.drawBitmap的时候就触发了空指针(错误信息里提到的getWidth()调用,就是createScaledBitmap内部对传入的Bitmap做检查时触发的)。
下面给你拆解可能的原因和对应的修复办法:
常见原因&修复步骤
资源文件不存在或命名错误
先去检查R.mipmap.ic_launcher这个资源是不是真的存在:看看mipmap目录(比如mipmap-hdpi、mipmap-mdpi这些文件夹)里有没有对应的图标文件,文件名是不是和代码里的完全一致(注意大小写,Android资源文件名是区分大小写的)。要是资源被误删或者改名了,decodeResource肯定返回null。Context对象无效
你用到的context是不是处于可用状态?比如如果这段代码是在自定义View的构造函数里执行的,或者在Activity还没完成初始化(比如onCreate之前)就调用了,这时候context.getResources()可能还没法正常工作。建议把资源加载的代码移到onCreate、onStart或者自定义View的onAttachedToWindow方法里执行,确保Context已经初始化完成。资源本身损坏或格式不支持
有时候图标文件本身有问题——比如格式是Android不支持的(比如WebP在低版本系统上可能有兼容性问题),或者文件损坏了。你可以试着替换成一个确定没问题的图片资源(比如系统自带的其他图标),看看能不能正常解码。
优化后的安全代码
为了避免崩溃,同时方便排查问题,最好在使用Bitmap之前加上空判断,还可以加上异常捕获:
Bitmap android_guy = null; try { // 先加载原始Bitmap Bitmap originalBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher); if (originalBitmap != null) { // 缩放Bitmap android_guy = Bitmap.createScaledBitmap(originalBitmap, 50, 50, true); // 回收原始Bitmap,避免内存泄漏 originalBitmap.recycle(); } else { // 原始Bitmap加载失败,打印日志排查 Log.e("BitmapLoad", "Failed to decode resource: R.mipmap.ic_launcher"); } } catch (Exception e) { e.printStackTrace(); Log.e("BitmapLoad", "Error loading bitmap", e); } // 确认Bitmap有效再绘制 if (android_guy != null) { canvas.drawBitmap(android_guy, width/2, 0, null); } else { // 这里可以加个降级逻辑,比如绘制一个默认的矩形提示资源加载失败 Paint paint = new Paint(); paint.setColor(Color.RED); canvas.drawRect(width/2 - 25, 0, width/2 + 25, 50, paint); }
这样就算资源加载失败,也不会直接崩溃,还能通过日志定位到问题所在。
内容的提问来源于stack exchange,提问作者Fahad

