一、如何解决NullPointerException in android.view.GLES20RecordingCanvas
在发布版本的最后一轮过设备时,在某老旧设备上出现了空指针异常
java.lang.NullPointerException
at android.view.GLES20RecordingCanvas.drawPatch(GLES20RecordingCanvas.java:97)
at android.graphics.NinePatch.draw(NinePatch.java:125)
at android.graphics.drawable.NinePatchDrawable.draw(NinePatchDrawable.java:189)
at android.widget.ScrollBarDrawable.drawThumb(ScrollBarDrawable.java:178)
at android.widget.ScrollBarDrawable.draw(ScrollBarDrawable.java:137)
at android.view.View.onDrawVerticalScrollBar(View.java:9532)
at android.view.View.onDrawScrollBars(View.java:9476)
at android.view.View.draw(View.java:11091)
at android.widget.AbsListView.draw(AbsListView.java:3428)
at android.view.View.getDisplayList(View.java:10455)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.drawChild(ViewGroup.java:2858)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2497)
at android.view.View.draw(View.java:11067)
at android.view.View.getDisplayList(View.java:10455)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2605)
at android.view.View.getDisplayList(View.java:10418)
at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:879)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:1955)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1661)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2505)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4945)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
开始出现闪退时觉得很惊讶,抓了日志马上谷歌。发现原来是android 4.0.X对不支持.9图片硬件加速,而从android4.0.x(SDK 14)开始系统默认打开硬件加速。
解决方法:view取消硬件加速
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
二、扩展阅读
在自定义控件或者自定义绘画时,应该注意使用的api是否支持硬件加速,以避免出现闪退情况
First supported API level | ||||||||||||||
Canvas | ||||||||||||||
drawBitmapMesh() (colors array) | 18 | |||||||||||||
drawPicture() | 23 | |||||||||||||
drawPosText() | 16 | |||||||||||||
drawTextOnPath() | 16 | |||||||||||||
drawVertices() | ✗ | |||||||||||||
setDrawFilter() | 16 | |||||||||||||
clipPath() | 18 | |||||||||||||
clipRegion() | 18 | |||||||||||||
clipRect(Region.Op.XOR) | 18 | |||||||||||||
clipRect(Region.Op.Difference) | 18 | |||||||||||||
clipRect(Region.Op.ReverseDifference) | 18 | |||||||||||||
clipRect() with rotation/perspective | 18 | |||||||||||||
Paint | ||||||||||||||
setAntiAlias() (for text) | 18 | |||||||||||||
setAntiAlias() (for lines) | 16 | |||||||||||||
setFilterBitmap() | 17 | |||||||||||||
setLinearText() | ✗ | |||||||||||||
setMaskFilter() | ✗ | |||||||||||||
setPathEffect() (for lines) | ✗ | |||||||||||||
setRasterizer() | ✗ | |||||||||||||
setShadowLayer() (other than text) | ✗ | |||||||||||||
setStrokeCap() (for lines) | 18 | |||||||||||||
setStrokeCap() (for points) | 19 | |||||||||||||
setSubpixelText() | ✗ | |||||||||||||
Xfermode | ||||||||||||||
PorterDuff.Mode.DARKEN (framebuffer) | ✗ | |||||||||||||
PorterDuff.Mode.LIGHTEN (framebuffer) | ✗ | |||||||||||||
PorterDuff.Mode.OVERLAY (framebuffer) | ✗ | |||||||||||||
Shader | ||||||||||||||
ComposeShader inside ComposeShader | ✗ | |||||||||||||
Same type shaders inside ComposeShader | ✗ | |||||||||||||
Local matrix on ComposeShader | 18 |
画布Canvas的scale方法
Drawing operation to be scaled | First supported API level |
drawText() | 18 |
drawPosText() | ✗ |
drawTextOnPath() | ✗ |
Simple Shapes* | 17 |
Complex Shapes* | ✗ |
drawPath() | ✗ |
Shadow layer | ✗ |
关注最新api请移步官网链接
https://developer.android.com/guide/topics/graphics/hardware-accel.html
说明:因为实际的错误堆栈会知道本人开发的实际项目,所以本博客的错误堆栈使用StackoverFlow问题中的内容。