webview的硬件加速

 Android从3.0(API Level 11)开始,在绘制View的时候支持硬件加速,充分利用GPU的特性,使得绘制更加平滑,但是会多消耗一些内存。

      开启或关闭硬件加速:

      由于硬件加速自身并非完美无缺,所以Android提供选项来打开或者关闭硬件加速,默认是关闭。可以在4个级别上打开或者关闭硬件加速:

      Application级别:<applicationandroid:hardwareAccelerated="true" ...>

      Activity级别:<activity android:hardwareAccelerated="false" ...>

      Window级别:

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

      注意:目前为止,Android还不支持在Window级别关闭硬件加速。

      View级别:

myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

      注意:目前为止,Android还不支持在View级别开启硬件加速。

      检测当前是否启用了硬件加速:
复制代码

// 方法一
// 此方法返回true,如果myView挂在一个开启了硬件加速的Window之下,
// 也就是说,它在绘制的时候不一定使用了硬件加速,getDrawingCache
myView.isHardwareAccelerated();
                        
// 方法二
// 返回true,如果canvas在绘制的时候启用了硬件加速
// 尽量采用此方法来判断是否开启了硬件加速
canvas.isHardwareAccelerated();

复制代码

      理解View的绘制模型:

      1.没有硬件加速:invalidate the view hierarchy ------> draw the view hierarchy

      2.有硬件加速:invalidate the view hierarchy ------> record and update the display list ------> draw the display list

      硬件加速的限制:

      目前,Android对硬件加速的支持并非完美,有些绘制操作在开启硬件加速的情况下不能正常工作(具体的列表可以参考Android开发者文档)。

      不过Android可以保证内置的组件和应用支持硬件加速。因此,如果应用中只使用了标准UI组件,可以放心开启硬件加速。

      随着Android的版本升级,相信一段时间之后,硬件加速可以得到完美的支持。

      开启硬件加速之后的异常反应:

      1.某些UI元素没有显示:可能是没有调用invalidate

      2.某些UI元素没有更新:可能是没有调用invalidate

      3.绘制不正确:可能使用了不支持硬件加速的操作, 需要关闭硬件加速或者绕过该操作

      4.抛出异常:可能使用了不支持硬件加速的操作, 需要关闭硬件加速或者绕过该操作








Android layer type与WebView白屏
分类: 技术文档 Android 2012-11-20 23:34 1997人阅读 评论(1) 收藏 举报

[html] view plaincopy

      


在项目中遇到WebView在加载图片的时候会出现白屏的情况,后来在xml设置了WebView属性,问题的到解决:

[html] view plaincopy

    <WebView   android:id="@+id/webview"  
                android:layout_width="fill_parent"  
                android:layout_height="fill_parent"  
                android:layerType="software"   
                android:scrollbars="none" />  


在网上也有layer的一些资料:

以下摘自http://blog.csdn.net/a345017062/article/details/7478667


先说说这三个layer。

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上面去。


LAYER_TYPE_NONE
这个就比较简单了,不为这个View树建立单独的layer


PS:GLSurfaceView和WebView默认Layertype都是none。


GLSurfaceView:
给GLSurfaceView设置为software或者hardware后,发现什么也画不出来了。得出结论:GLSurfaceView的Layer type只能是none


WebView:
以前使用WebView时碰到过一个问题,如果在WebView上面使用Animation,WebView的绘画区域不动。当时的解决方案是在进行动画之前对WebView进行截屏(drawingcache)。按上面的道理试了一下,设置一个hardware或者software的layer就OK了。

现在又碰到了另外一个问题,打开硬件加速后,在一些机器上面(我的是3.2)WebView有时会出现某一块区域白屏的问题。默认的layer type是none,改为hardware也不行,设置为software就解决了。当然关闭硬件加速也好了,可是那样的话程序整体就比较慢了。所以最终方案是整体硬件加速,出问题的WebView设置software


补充于2012.4.21:

加上这一句,可以让3D的绘制更快一些:getHolder().setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);


补充于2012.4.22

先说问题:
在硬件加速开启的情况下GLSurfaceView一旦被从View树上摘下来,会使整个窗口背景变黑,即使设置layer type为software也不管用。
经过两天的排查,发现了原因,我的程序是在C层由drawFrame(属于GLThread线程)来驱动进行绘画,当GLSurfaceView被摘下来时,GLSurfaceView的destroy方法被调用,我在destroy方法(属于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。这个可以参考Dev Guide

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果您关闭了 WebView硬件加速,那么您可能需要使用软件渲染来播放视频。您可以使用 Android SDK 提供的 MediaPlayer 类或者 ExoPlayer 库来实现。 使用 MediaPlayer 类播放视频的基本步骤如下: 1. 创建 MediaPlayer 实例。 2. 设置数据源,可以是本地文件或者网络地址。 3. 准备 MediaPlayer。 4. 开始播放。 示例代码如下: ```java MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setDataSource("your_video_file_path"); mediaPlayer.prepare(); mediaPlayer.start(); ``` 如果您需要在 WebView 中播放网络视频,您可以使用 ExoPlayer 库来实现。ExoPlayer 是 Google 推荐的一个用于播放多种媒体格式的开源库,可以轻松地实现视频播放、缓存和跨平台支持等功能。 您需要在 WebView 中注册一个 WebChromeClient,然后在 onShowCustomView 方法中创建一个 View 并将其添加到 WebView 中。在这个 View 中,您可以使用 ExoPlayer 来播放视频。 示例代码如下: ```java private WebView webView; private FrameLayout videoLayout; private View videoView; private SimpleExoPlayer exoPlayer; webView.setWebChromeClient(new WebChromeClient() { @Override public void onShowCustomView(View view, CustomViewCallback callback) { super.onShowCustomView(view, callback); videoView = view; videoLayout.addView(videoView); exoPlayer = new SimpleExoPlayer.Builder(context).build(); exoPlayer.setVideoSurfaceView((SurfaceView) videoView); exoPlayer.setMediaItem(MediaItem.fromUri("your_video_url")); exoPlayer.prepare(); exoPlayer.play(); } @Override public void onHideCustomView() { super.onHideCustomView(); videoLayout.removeView(videoView); exoPlayer.release(); } }); ``` 其中,videoLayout 是一个 FrameLayout,用于将视频 View 添加到 WebView 中。在 onShowCustomView 方法中,我们创建了一个 SurfaceView 并将其设置为 ExoPlayer 的视频 Surface,然后设置要播放的媒体项并准备 ExoPlayer。在 onHideCustomView 方法中,我们从 videoLayout 中移除视频 View 并释放 ExoPlayer。 需要注意的是,如果您关闭了 WebView硬件加速,使用软件渲染来播放视频可能会导致性能下降和卡顿等问题。因此,建议您在必要的情况下开启 WebView硬件加速,并在播放视频时使用硬件加速

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值