注:轉自mui dcloud
http://ask.dcloud.net.cn/article/55
從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”字段:

要開啟硬件加速設置值為true,關閉硬件加速則設置值為false。不配置的話默認是auto。
保存提交到App雲端打包才能生效。
- 離線打包配置的方法
打開工程的AndroidManifest.xml文件,切換到代碼視圖模式,在application節點下修改“android:hardwareAccelerated”屬性值:
要開啟硬件加速設置值為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”字段:
設置值為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。
共勉!