Android 4.0硬體加速的使用
1.Android4.0硬體加速的使用
1.1硬體加速的控制級別
啟用硬體加速的最簡單方法就是為整個系統開啟硬體加速的全域性設定。如果你的程式是標準View或者是Drawable則硬體加速的全域性設這並不會造成不良的影響。然而硬體加速並不支援所有2D畫的操作,所以開啟硬體加速可能會對使用自定義元件的應用程式造成影響,問題常常表現在不可見的元素異常和錯誤的畫素渲染,為了解決這個問題Android可以讓你選擇啟動或者禁用以下級別的硬體加速:ApplicationActivityWindow和View。
1.1.1Application級別
在你的AndroidManifest檔案中新增屬性標記,以便為整個應用程式使用硬體加速。
1.1.2Activity級別
如果你的應用程式不能在Application應用級別表現良好的話,則可以使用對Activity進行單獨控制。要啟動或者禁用一個Activity的硬體加速,你可以使用activity的android:hardwareAccelerated屬性。下面的一個列子使整個Application啟用硬體加速,但是對一個Activity禁止使用硬體加速。
1.1.3Window級別
如果你需要更細粒度的控制,你可以通過如下程式碼給window進行加速。
- getWindow().setFlags(
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
注意:現階段你不能在Window級別對它禁用硬體加速。
1.1.4View級別
我們可以對單獨的View在執行時階段禁用硬體加速。我們可以使用如下程式碼:
- myView.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
注意:現階段不能夠在View級別進行硬體加速。
1.2判斷一個View是否已經啟用了硬體加速
有時候我們需要知道一個應用程式是否已經啟用了硬體加速,特別是針對一些自定義控制元件。因為你的應用程式做了很多自定義“畫”的操作,但並不是所有的過程都支援新的“畫”的渲染過程。
有兩種不同的方法來檢查Application是否啟用了硬體加速:
1.2.1使用View.isHardwareAccelerated()如果返回true則可以說明這個View所在的視窗已經啟用了硬體加速。
1.2.2Canvas.isHardwareAccelerated()如果返回true則說明這個Canvas已經啟用了硬體加速。
如果你必須要在你的繪畫程式碼中進行是否已經加速的檢查,如果可能的話請使用Canvas.isHardwareAccelerated()來代替View.isHardwareAccelerated()。當一個View是存在於一個已經加速的Windows上時,任然可以使用沒有硬體加速的Canvas進行繪畫,這場發生在,比如,當我們把一個View畫到Bitmap上然後用作快取。
2.Android4.0的繪製模型
當開啟了硬體加速,Android框架將會使用一種新的繪製模型,這種模型將會使用顯示列表把你的應用顯示到螢幕上。要完全理解顯示列表和他們如何影響你的應用程式,理解Android4.0如何在非硬體加速的情況下如何繪製Views是很有必要的,下面將分別介紹軟體加速和硬體加速。
2.1基於軟體的繪製模型
在基於軟體繪製模型中,View的繪製遵循以下兩步:1.使整個控制元件層級無效。2.對層級進行繪製。
當一個應用程式需要更新它UI的一部分時,它將會呼叫內容發生改變的View的invalidate()方法(或者invalidate的變體)。Invalidate的訊息按照View的層級關係向上傳遞用以計算需要重畫的部分(即髒區域)。然後Android系統會對和髒區域有交集的所有View進行繪製,不幸的是這種模型中有兩個缺點:
2.1.1在這種模型中當在不同的層進行畫的時候,會額外執行很多程式碼。例如一個Button是位於另外一個View之上,當對Button呼叫Invalidate()時,Android就會對這個View進行重繪,即便這個View沒有發生任何變化。
2.1.2第二個問題是這種繪製模型會隱藏你Application中的Bug。因為Android系統會對和髒區域有交集的View進行重繪,在這種情況下如果一個view的內容發生了改變,即便這個View的Invalidate()的方法並沒有得到呼叫,它也可能被重繪。你便會依賴呼叫了invalidate()的其他的控制元件以便獲得正確的行為,因此每當你的Application發生改變時,這種行為多要隨之發生改變。也是基於次因,在你的自定義控制元件中你必須不斷地呼叫invalidate()方法,當你的資料或者是狀態會影響View的繪製程式碼時。
注意:Android的View當它們的屬性發生改變時會自動的呼叫Invalidate()。比如,你改變一個Textview的背景或者是它的文字。
2.2基於硬體加速模型
Android系統仍然通過invalidate()和draw()去請求螢幕更新和重新渲染,但是實際處理畫的方式是不同的。不是立即執行畫的命令,Android而會將所有畫的命令記錄在一個顯示列表裡面,這個顯示列表包含了輸出的View層級的繪製程式碼。還有一個優化就是Android在顯示列表中只會記錄和更新顯示層級中通過呼叫invalidate()函式被標記為“髒”的view。沒有被請求重新整理的view可以通過重新請求先前的顯示列表以便重畫。新的繪製模型包括有三個步驟:1.禁用整個View層級。2.記錄和更新顯示列表。3.繪製顯示列表。
使用這個模型你不能依賴一個View和髒區域有交集就會執行draw()方法。要確保Android系統記錄了一個View的顯示列表,你必須呼叫invalidate()方法,如果忘記了呼叫重新整理,會使View即便是發生了改變後也會看起來相同,這是一個比較容易發現bug的方式。
使用顯示列表的方式對動畫的表現也是很有好處的,因為設定指定的屬性值,比如透明度或者旋轉,就不需要請求重新整理目標View(這將自動執行)。這項優化也應用於有顯示列表的Views(啟用了硬體加速的View),例如,現在有一個LinearLayout包含了一個ListView和Button,listview在button的上面。這時候LinearLayout的顯示列表如下所示:
◆DrawDisplayList(ListView);
◆DrawDisplayList(Button);
假設你現在你想更新這個Listview的不透明度,在設定Listview的setAlpha(0.5f)屬性之後,LinearLayout的顯示列表應該包含如下:
◆SaveLayerAlpha(0.5)
◆DrawDisplayList(ListView)
◆Restore
◆DrawDisplayList(Button)
這時候繪製Listview的複雜過程就會省略了,取而代之的是簡單的更新了LinearLayout的顯示列表。如果一個應用程式並沒有啟用硬體加速,Listview和它的父view的畫的程式碼都會重新執行。
3.Android4.0View的層
3.1層的分類
所有的Android版本都有能力對離屏緩衝進行渲染,或者是使用View的繪製緩衝,或者是使用Canvas.saveLayer()函式。離屏緩衝或者Layer能夠有很多種應用,例如能使處理複雜view的動畫效果或者應用一些合成效果都有更好地表現。例如你可以通過Canvas.saveLayer()的方式來對View做一個漸入漸出效果同時把它渲染到Layer中,然後再加上不透明效果合成後顯示到螢幕上。
由Android3.0開始你就能夠通過View.setLayerType()方法對何時以及如何使用層有了更多的控制,這個API具有兩個引數一個是你想使用的層型別,另外一個是可選引數Paint表明了Layer是如何被疊加的。你可以把Paint引數應用到顏色過濾上,特別是混合模式或者是對一個layer進行不透明效果。一個View可以使用如下的三種layer型別之一:
◆LAYER_TYPE_NONE:這個View將被按普通的方式進行渲染,但是不會返回一個離屏的緩衝,這個是預設的行為。
◆LAYER_TYPE_HARDWARE:如果這個應用被硬體加速的話,這個View將會在硬體中渲染為硬體紋理,如果應用程式並沒有被硬體加速,則其效果和LAYER_TYPE_SOFTWARE是相同的。
◆LAYER_TYPE_SOFTWARE:此View通過軟體渲染為一個bitmap。
3.2層的使用
使用層的型別取決於你的目的:
3.2.1效能:使用硬體層來渲染一個View成為硬體紋理。一旦一個View被渲染為一個層,它的繪製程式碼將不會得到執行,直到你呼叫了invalidate()函式。對於一些動畫,比如透明動畫可以直接應用到一個層上,這是GPU最有效率的使用方式。
3.2.2顯示效果:使用硬體或者軟體層和Paint來對一個View進行特殊的視覺處理,例如你可以對一個View通過使用ColorMatrixColorFilter來實現黑白效果。
3.2.3相容性:使用軟體層型別會強制使一個view在軟體中被渲染。如果一個view是硬體加速的話(比如你設定整個應用程式是硬體加速的話),同時有渲染的問題,這是一種很簡單的方式來限制硬體繪製流程。
3.3View的層和動畫的關係
當你的應用程式已經使用了硬體加速的話,硬體層能夠帶來更為快速和更為平滑的動畫效果。當對一個複雜的View進行動畫操作時,因為要進行很多的畫操作,所以並不可能總是能達到60幀每秒。在這種情況下可以通過硬體層來渲染為硬體紋理來提高效能。硬體紋理操作可以用作對一個view進行動畫操作,當進行動畫的時候可以減少對View自身頻繁的重繪。除非你改變這個view的屬性(呼叫invalidate()方法)或者你手動的呼叫invalidate()。如果在你的應用中執行一個動畫,但是並沒有得到你想要的平滑效果,可以考慮為你要動畫的view開啟硬體層。
當一個View通過硬體層返回時,當所有的層疊加後最終的畫面顯示在螢幕時,View一些屬性會被同時被處理。設定這些屬性是十分有效率的,因為他們不需要View去invalidate和重繪。如下的屬性將影響層的疊加,設定這些屬性將會使View自動請求重新整理,而且不需要對View進行重繪。
◆alpha:改變層的透明度。
◆x,y,translationX,translationY:改變層的位置
◆scaleX,scaleY:改變層的大小
◆rotation,rotationX,rotationY:在3D空間內改變層的方向
◆pivotX,pivotY:指定它進行變形的原點位置
這些屬性是通過ObjectAnimator物件對一個view進行動畫操作時所使用的,如果你想訪問這些屬性,直接呼叫這些屬性的setter或者getter方法,例如想改變View的alpha則直接呼叫setAlpha()。如下的程式碼片段顯示了一個View通過Y軸進行3D旋轉。
- view.setLayerType(View.LAYER_TYPE_HARDWARE,null);
- ObjectAnimator.ofFloat(view,"rotationY",180).start();
因為硬體層會消耗視訊的記憶體,強烈的推薦你在作動畫的時候啟用他們,當動畫完成了之後禁用他們,你可以通過動畫監聽來完成這些。程式碼如下:
- View.setLayerType(View.LAYER_TYPE_HARDWARE,null);
- ObjectAnimatoranimator=ObjectAnimator.ofFloat(view,"rotationY",180);
- animator.addListener(newAnimatorListenerAdapter(){
- @Override
- publicvoidonAnimationEnd(Animatoranimation){
- view.setLayerType(View.LAYER_TYPE_NONE,null);
- }
- });
- animator.start();
4Android4.0提示和技巧
切換到硬體加速2D圖形可以立即增強表現,但是你還是需要通過如下的建議來設計你的應用程式來更有效率的使用GPU。
4.1減少你程式中使用View的數量
你係統中畫的view的數量越多,你的程式就會越慢,在軟體繪製的流程也是一樣的,減少view的數量是優化你UI的一個最簡單的方法。
4.2避免過多繪製
不要過多的疊加層,當一個View被其他view完全遮擋住了的話,最好把被遮擋的view移除掉。如果你需要繪製不同的層做一個疊加效果的話,考慮把這些層合併為一個層。就現在的硬體來看,有一個好的經驗就是動畫的每幀不要繪製多餘螢幕畫素2.5倍的畫素數量(bimap中的透明畫素也計算在內)。
4.3不要在繪製的方法中建立繪製物件
一個常見的錯誤就是當繪製方法被呼叫的時候,每次都要建立一個新的Paint或者Path。這將迫使垃圾回收器過於頻繁的執行,這將對緩衝和硬體的繪製造成影響。
4.4不要過於頻繁的修改形狀
以複雜的shapes,path和旋轉為例,這些繪製都會用到紋理的遮罩。每當你建立或者修改一個path,硬體渲染過程都會建立一個新的遮罩,這耗費的代價是相當大的。
4.5不要過於頻繁的修改bitmap
每當修改一次bitmap的內容,當你下次再繪製它的時候都會以GPU的紋理形式上傳一次。
4.6要小心使用alpha通道
當你使用setAlpha,AlphaAnimation或者ObjectAnimator設定一個View的透明效果時。它將需要2倍離屏的渲染緩衝填充率,當應用一個alpha到一個大的View上的時候,考慮設定view層的型別為LAYER_TYPE_HARDWARE。
本文作者的微博為http://weibo.com/zuiniuwang歡迎大家與他聯絡。
相關文章
- Android的硬體加速Android
- android4.0 開啟硬體加速後應用執行出錯 android4.0 開啟硬體加速後應用執行出錯...Android
- 理解Android硬體加速的小白文Android
- 在 CSS 動畫中使用硬體加速(翻譯)CSS動畫
- Android硬體加速(二)-RenderThread與OpenGL GPU渲染AndroidthreadGPU
- # HenCoder Android 自定義 View 1-8 硬體加速AndroidView
- 自定義View的硬體加速問題View
- 硬體3D加速指南(轉)3D
- 如何用 GPU硬體層加速優化Android系統的遊戲流暢度GPU優化Android遊戲
- 硬體加速gpu計劃開還是不開 win10硬體加速gpu計劃有用嗎GPUWin10
- 視訊工具箱和硬體加速
- win10關閉硬體加速怎麼關閉_win10禁用顯示卡硬體加速怎麼操作Win10
- win10硬體加速沒有gpu計劃 強制開啟win10硬體加速gpu計劃的方法Win10GPU
- windows10系統關閉硬體加速的方法Windows
- win10硬體加速怎麼調高_win10硬體加速如何設定成最高效能Win10
- Android中GPU硬體加速控制及其在2D圖形繪製上的侷限AndroidGPU
- 學習通過CSS硬體加速提升你網站的效能CSS網站
- 微軟推送Windows 10照片UWP更新:新增硬體加速功能微軟Windows
- WPF概述(硬體加速及解析度無關性)
- 谷歌全面開源 MLIR 及生態聯盟,全球 95% 的加速器硬體都在使用谷歌
- Now in Android:02 - 歡迎使用 Android Studio 4.0 !Android
- Android硬體點陣圖填坑之獲取硬體畫布Android
- win10系統下如何開啟顯示卡硬體加速Win10
- Win7系統怎麼設定顯示卡硬體加速Win7
- 全同態加密的硬體加速:讓機器學習更懂隱私保護加密機器學習
- Android獲取硬體裝置資訊Android
- Android的硬體抽象層模組編寫規範Android抽象
- XCKU115硬體加速卡學習資料儲存:基於Xilinx XCKU115的半高PCIe x8 硬體加速卡
- Windows10系統中edge怎麼設定硬體加速GPUWindowsGPU
- WDS:Android使用者手機問題14%與硬體故障有關Android
- Android 平臺開啟硬體解碼logAndroid
- Android硬體程式設計學習資料Android程式設計
- Android Things 專題 2 硬體介紹Android
- 業界 | 谷歌開源DeepLearn.js:可在網頁上實現硬體加速的機器學習谷歌JS網頁機器學習
- 深度學習的異構硬體加速:TPU 特性與資料中心的 ASIC 應用(概述篇)深度學習
- 英特爾想要比特幣挖礦硬體“加速器”專利比特幣
- 在Linux桌面上安裝Moonlight並提示找不到硬體加速Linux
- 使用Windows PowerShell來檢視硬體資訊Windows