转自:http://blog.csdn.net/a345017062/article/details/7478667
问题:WebView白屏(有数据)
报错:[ERROR:in_process_view_renderer.cc(189)] Failed to request GL process. Deadlock likely: 0
解决:WebView设置setLayerType(View.LAYER_TYPE_SOFTWARE,null)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); }分析:WebView继承View,View中有三种layer type分别为
/** * Indicates that the view does not have a layer. * * @see #getLayerType() * @see #setLayerType(int, android.graphics.Paint) * @see #LAYER_TYPE_SOFTWARE * @see #LAYER_TYPE_HARDWARE */ public static final int LAYER_TYPE_NONE = 0; /** * <p>Indicates that the view has a software layer. A software layer is backed * by a bitmap and causes the view to be rendered using Android's software * rendering pipeline, even if hardware acceleration is enabled.</p> * * <p>Software layers have various usages:</p> * <p>When the application is not using hardware acceleration, a software layer * is useful to apply a specific color filter and/or blending mode and/or * translucency to a view and all its children.</p> * <p>When the application is using hardware acceleration, a software layer * is useful to render drawing primitives not supported by the hardware * accelerated pipeline. It can also be used to cache a complex view tree * into a texture and reduce the complexity of drawing operations. For instance, * when animating a complex view tree with a translation, a software layer can * be used to render the view tree only once.</p> * <p>Software layers should be avoided when the affected view tree updates * often. Every update will require to re-render the software layer, which can * potentially be slow (particularly when hardware acceleration is turned on * since the layer will have to be uploaded into a hardware texture after every * update.)</p> * * @see #getLayerType() * @see #setLayerType(int, android.graphics.Paint) * @see #LAYER_TYPE_NONE * @see #LAYER_TYPE_HARDWARE */ public static final int LAYER_TYPE_SOFTWARE = 1; /** * <p>Indicates that the view has a hardware layer. A hardware layer is backed * by a hardware specific texture (generally Frame Buffer Objects or FBO on * OpenGL hardware) and causes the view to be rendered using Android's hardware * rendering pipeline, but only if hardware acceleration is turned on for the * view hierarchy. When hardware acceleration is turned off, hardware layers * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> * * <p>A hardware layer is useful to apply a specific color filter and/or * blending mode and/or translucency to a view and all its children.</p> * <p>A hardware layer can be used to cache a complex view tree into a * texture and reduce the complexity of drawing operations. For instance, * when animating a complex view tree with a translation, a hardware layer can * be used to render the view tree only once.</p> * <p>A hardware layer can also be used to increase the rendering quality when * rotation transformations are applied on a view. It can also be used to * prevent potential clipping issues when applying 3D transforms on a view.</p> * * @see #getLayerType() * @see #setLayerType(int, android.graphics.Paint) * @see #LAYER_TYPE_NONE * @see #LAYER_TYPE_SOFTWARE */ public static final int LAYER_TYPE_HARDWARE = 2;
LAYER_TYPE_SOFTWARE:表明视图有一个软件渲染层。无论是否开启硬件加速,都会有一张Bitmap(software layer),并在上面对WebView进行渲染。
好处:在进行动画,使用software可以只画一次View树,很省。
什么时候不要用:
View树经常更新时不要用。尤其是在硬件加速打开时,每次更新消耗的时间更多。因为渲染完这张Bitmap后还需要再把这张Bitmap渲染到hardware layer上面去。
LAYER_TYPE_HARDWARE:
表明视图有一个硬件渲染层。硬件加速关闭时,作用同software。硬件加速打开时会在FBO(Framebuffer Object)上做渲染,在进行动画时,View树也只需要画一次。
两者区别:
1.一个是渲染到Bitmap,一个是渲染到FB上。
2.hardware可能会有一些操作不支持(出现白屏)
两者相同:
都是开了一个buffer,把View画到这个buffer上面去。
PS:GLSurfaceView和WebView默认LayerType都是NONE。
GLSurfaceView:给GLSurfaceView设置为software或者hardware后,发现什么也画不出来了。得出结论:GLSurfaceView的LayerType只能是NONE。
WebView:
以前使用WebView时碰到过一个问题,如果在WebView上面使用Animation,WebView的绘画区域不动。当时的解决方案是在进行动画之前对WebView进行截屏(drawingcache)。按上面的道理试了一下,设置一个hardware或者software的layer就OK了。
现在又碰到了另外一个问题,打开硬件加速后,在一些机器上面(我的是3.2及HTC 4.4)WebView有时会出现某一块区域白屏的问题。默认的LayerType是NONE,改为hardware也不行,设置为software就解决了。当然关闭硬件加速也好了,可是那样的话程序整体就比较慢了。所以最终方案是整体硬件加速,出问题的WebView设置software。
补充1:
加上这一句,可以让3D的绘制更快一些:getHolder().setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);
补充2:
问题:
在硬件加速开启的情况下GLSurfaceView一旦被从View树上摘下来,会使整个窗口背景变黑,即使设置LayerType为software也不管用。
经过两天的排查,发现了原因,我的程序是在C层由drawFrame(属于GLThread线程)来驱动进行绘画,当时GLSurfaceView被摘下来时,GLSurfaceView的destroy方法被调用,我在destory方法(属于UI线程)中直接调用了GLThread线程的结束方法。而GLSurfaceView.creat, sizeChanged,destroyed在UI线程,Render.create,sizeChanged,drawFrame在GLThread线程。因此,出现了UI线程直接调用GLThread线程的方法问题。最终通过GLSurfaceView.queueEvent向GLThread线程发送Runnable,问题得到解决。
看来,还是软渲染的容错能力比较强,一开硬件加速,底层就比较脆弱了。
结论:一定要搞清楚哪个是UI线程,哪个是GLThread线程。
补充以上寻找问题过程中发现的知识点:
hardware acclerator是对整个窗口进行加速,在硬件加速打开时View.isHardwareAcclerator返回true。但每个View可能被渲染到的Canvas是不同的,比如View可能被通过setLayer设置layer,这时,Canvas.isHardwareAccelerator返回false
Android提供了三种硬件加速是否开启的控制级别,分别是Application,Activity,Window,View。这个可以参考DevGuide。