关于Android硬件加速技术分析

从Android3.0(API Level 11)开始,支持硬件加速,可充分利用GPU的特性,使得界面渲染更加平滑,但是会消耗更多内存RAM。
但是硬件加速自身并非完美,在某些Android5的rom上,由于内存RAM分配的问题,如果代码不当,会引发闪屏、花屏等渲染问题。
本文探讨的就是如何利用硬件加速并避免踩坑。

硬件加速的好处

硬件加速对渲染的流畅度有大幅提升。
在开启硬件加速后,上下拖动列表的感觉是没有跳帧的平滑拖动感,如果没有硬件加速,拖动时能感受到有丢帧。
在窗体切换动画上也类似,硬件加速开关对切换动画的影响很大。
对于video、canvas、webgl,没有硬件加速是没法商用的,Android webview里video标签里的视频如果没有硬件加速会看不到画面。

硬件加速的代价

硬件加速属于双缓冲机制,使用显存进行页面渲染(使用较少的物理内存),导致更频繁的显存操作,可能引起以下现象:
白屏、花屏、闪屏;
低RAM内存配置手机上闪退。
虽然新出的Android5.0的手机整体配置较高(显存较大),但是如果页面中使用大量图片或者过于复杂的CSS样式时同样容易出现白屏、花屏、闪屏现象。

解决硬件加速造成的问题有2个思路,1.降低页面的内存占用,给硬件加速腾出RAM;2.在适当的地方关闭硬件加速。

方案1:通过其他方式降低页面的内存占用,给硬件加速腾出RAM

App中占用RAM比较多的地方包括同时显示的webview的数量和webview的dom体积以及图片体积。
大多数开发者报App闪屏,一问下来大多数是开启硬件加速且这3块的代码有问题。
努力优化这3块就能解决问题。
我们遇到有开发者的App一个界面并显3个webview,其中一个webview里显示几十张体积数M的图,这样的App渲染必然异常。
- 图片处理

图片是已知问题中最高概率发生的问题,也是解决起来最简单有效的问题。 
把图片裁剪到几十K,即便还是3个webview也不再出问题。 
有些app里设了很大的背景图,此时非常影响渲染,请尽量不要设背景图或使用少量的背景图。 
如果要显示清晰高清图,尽量设计成不在同一界面并显多张高清大图。 
- webview处理

关于webview的并显数量,常见的并显结构有解决列表滚动的父子窗体、侧滑菜单webview、底部选项卡webview。 
其中底部选项卡webview最占内存,如果必须使用这种设计,就更要注意图片体积的控制。 
webview侧滑菜单其实可以尽量改为div方式的侧滑菜单。 
webview侧滑菜单比div侧滑菜单的优势是菜单rom复杂也可以平滑移动,以及可以盖住native的控件比如plus.map,但我们仍然建议非必要不使用webview侧滑菜单,把侧滑菜单设计的简单点,采用div方式会更节约内存。 
解决列表流畅滚动的父子窗体,制作时注意把子窗体dock,dock模式能降低渲染压力,减少并显的webview的显示区域。 
- HTML、JS、CSS代码处理

减少dom复杂度,很多开发者的代码里div反复单层嵌套,毫无意义并且增加dom解析和渲染的压力; 
减少重型js框架的依赖,angular、jq能不用就不用; 
减少css代码,尽可能的少写css,不要写互相覆盖的无效css,不要使用复杂的css计算模型; 
css里少用百分比方式的定位和宽高计算,少用padding、margin。有的开发者的界面元素刚显示时在这个位置,过一会儿抖动一下往下移动了几个像素,就是因为margin、padding生效晚导致二次渲染。 
如果有图片轮播,且发生闪屏,把自动轮播禁用掉,不要自动切换图片。 
- webview动画切换改为pop-in

pop-in动画的切换是有自动截图处理的,这种动画发生花屏闪屏的概率要比较低。 
- webview的出入栈控制

为了节省内存,不显示的webview默认是出栈的。
在返回时,之前的窗体会重新入栈,有时这种重新入栈渲染的过程也会发生白屏。
如果你的app内存占用不高,可以控制一些界面不出栈,返回时就会直接看到之前的内容。
控制不出栈的api在http://www.html5plus.org/doc/zh_cn/webview.html,这里搜render来控制。

方案2:在适当的地方开启或关闭硬件加速

如果方案1的优化内存占用仍然不管用,那么方案2也需要使用。
在5+App可以从两个级别对硬件加速进行控制:

App级别

程序级别开关是设置整个程序是否使用硬件加速,关闭后程序中所有页面将都不可使用硬件加速功能,可通过以下方式操作:

- HBuilder中配置的方法

打开应用的manifest.json文件,切换到“代码视图”,在plus->distribute->google节点下添加“hardwareAccelerated”字段:

关于Android硬件加速技术分析_第1张图片

要开启硬件加速设置值为true,关闭硬件加速则设置值为false。不配置的话默认是auto。
保存提交到App云端打包才能生效。

- 离线打包配置的方法

打开工程的AndroidManifest.xml文件,切换到代码视图模式,在application节点下修改“android:hardwareAccelerated”属性值:
关于Android硬件加速技术分析_第2张图片

要开启硬件加速设置值为true,关闭硬件加速则设置值为false。
保存后重新编译即可生效。

Webview窗口级别

除了App级别,还可以对单个Webview控制是否开启硬件加速功能,比如App关闭了硬件加速,但某个webview又打开了硬件加速:

- 新开Webview窗口是否开启硬件加速

创建Webview窗口时(注意创建完毕再修改无效),可设置WebviewStyle参数的hardwareAccelerated属性值控制是否开启硬件加速:

var styles = {hardwareAccelerated:true}; // true表示开启Webview的硬件加速,false表示关闭Webview的邮件加速
var webview = plus.webview.create( "url", "id", styles );   
webview.show();
  • 设置首页webview是否开启硬件加速

    上面的新开webview时设置硬件加速对首页是无效的,因为首页不是js创建的。首页webview的硬件加速单独配置需要在manifest里进行。
    注意此配置与全局设置不同,虽然都在manifest配置,但此配置仅是对首页生效的,并非全局App的硬件加速配置。
    打开应用的manifest.json文件,切换到“代码视图”,在plus节点下添加“hardwareAccelerated”字段:
    关于Android硬件加速技术分析_第3张图片

    设置值为true表示开启硬件加速,false表示关闭硬件加速。

关于硬件加速默认的auto值的说明,即不同平台上5+runtime默认开启或关闭硬件加速的策略

如果开发者不手动配置硬件加速的开关,将执行5+runtime的默认策略。这里说明下默认策略。
大部分手机上5+runtime是默认开启硬件加速的。但一些三方的Android5 rom对Webview的处理有bug,所以在这些设备上,我们默认将Webview的硬件加速功能关闭,详细情况为:

| 设备品牌 | Android系统 | 默认Webview硬件加速 |

| ---:--- | ---:--- | ---:--- |

| 小米 | 5.x | 关闭 |

| 三星 | 5.x | 关闭 |

| 魅族 | 5.x | 关闭 |

| 联想 | 5.x | 关闭 |

| HTC | 5.x | 关闭 |

| 摩托 | 5.x | 关闭 |

| 其它 | 5.0及以上 | 开启 |

可以通过5+ API查询Webview默认硬件加速是否开启

但注意此api即defauleHardwareAccelerated,是我们的引擎的默认策略查询,开发者手动打开硬件加速后,并不会更改这个值。
检测硬件加速是否开启,一方面看上下滑动的流畅度,另一种方法是放一个video标签,看看视频是否有画面。

由于这些Android5 rom的bug导致硬件加速被默认关闭时,此时非常容易发生的问题就是开发者发现怎么视频没有画面或canvas卡的一塌糊涂,细心的开发者还会发现某些Android5的手机动画流畅度还不及Android4,其实都是因为硬件加速的问题。

参考前述方式优化代码,然后强制打开硬件加速,一般也能解决问题。

特别的,如果想播放视频,有2种方案:

1. 对播放视频的webview单独开硬件加速,创建这个webview时参考上面的方法开启硬件加速。

2. 调用外部原生播放器单独播放视频,http://ask.dcloud.net.cn/question/614

与iOS相比,Android确实是不那么友好的世界,优秀的开发者之所以优秀,就是耐得住性子做调优,成功的做出了精良的App。
共勉!

你可能感兴趣的:(Android)