android圖形系統詳解五:Android繪制模式

上一篇:/kf/201204/126774.html

當硬加速被啟用,Android框架利用一個新的繪制模式來把你的應用呈現到屏幕,這個模式利用瞭一個顯示列表.要完全理解顯示列表以及它如何影響你的應用,先要理解android如何在非硬加速下繪制View.下面的小節描述瞭軟加速的和硬加速的繪制models.

軟件繪制模式

  在軟件繪制模式,view按以下兩步進行繪制:

1使整個View層級都變得無效

2繪制所有的View層級

 

 

  任何時候一個應用需要更新部分UI時,它應在任何改變瞭內容的View上調用invalidate()(或它的任一變體),使界面無效的消息在整個View層級中傳播以計算應被繪制的屏幕區域(臟區域).之後Android系統繪任View層級中所有與臟區域有交集的View. 不幸的是,這種繪制模式有兩個缺點:

第一,這個模式需要在每個繪制路徑中都執行很多代碼.比如,如果你的應用在一個button上調用瞭invalidate()並且這個button位於另一個view之上,即使這個View沒有變化,Android系統也會繪制這個View.

第二個問題是這個繪制模式可能隱藏你應用中的bug.因為Android系統會繪制與臟區域有交集的view們,那麼一個你改變瞭內容的view可能在沒有被調用invalidate()時也會被重繪瞭.當這種情況發生時,你隻能依賴那個需要重繪的view來獲得正確的行為.但這個行為可能在你每次修改你的應用時都會改變.因此,在任何你修改瞭數據或狀態而影響到繪制代碼的時候,你總是應該在你的自定義view上調用invalidate().

 

 

  註:Androidview們會在它們的屬性被改變時自動調用invalidate(),比如一個TextView的背景和文本改變時.

硬加速繪制模式

  Android系統依然使用invalidate()和draw()來請求屏幕更新並畫出views,但是對實際的繪制處理卻不一樣.現在不是在收到繪制命令立即執行瞭,而是Android系統把繪制命令記錄到顯示列表中,這個列表中包含瞭View層級的繪制代碼的輸出.另一個優化是Android系統隻需為那些通過invalidate()標記為臟的View記錄和更新顯示列表.沒有被invalidated的Views可以簡單地使用先前的顯示列表中的記錄進行重繪.新的繪制模式包含三個階段:

1使整個View層級都無效

2記錄並更新顯示列表

3畫顯示列表

 

 

  使用此模式,你再不能依靠讓View與臟區域交界而使它的draw()方法被調用.要保證Android系統記錄下view的顯示列表,你必須調用invalidate().忘記這樣做會導致一個view總是一個模樣,即使改變瞭它.但這是一個很容易被找出的bug.

 

 

  使用顯示列表還對提升動畫性能有益,因為設置瞭某個屬性,比如alpha或rotation等,不再需invalidating目標view(自動做瞭).這個優化也會應用到擁有顯示列表的view上(當你的應用被硬加速時的任何view).例如,假設有一個LinearLayout包含瞭一個ListView和一個Button,ListView位於Button之上,LinearLayout的顯示列表看起來如下:

DrawDisplayList(ListView)

DrawDisplayList(Button)

  假設現在你想改變ListView的opacity,在調用瞭ListView的setAlpha(0.5f)後,顯示列表現在包含如下項:

SaveLayerAlpha(0.5)

DrawDisplayList(ListView)

Restore

DrawDisplayList(Button)

 

 

  ListView復雜的繪制過程沒有被執行,而是僅更新瞭更簡單的LinearLayout的顯示列表.如果在一個未硬加速的應用中,列表和它爹的繪制代碼都會被重新執行.

不支持的繪制操作

  當啟用瞭硬加速,2D呈現管道會支持通用的Canvas繪制操作,也支持不常用的操作.所有的繪制操作被用來呈現widgets,layouts以及通用高級視覺效果,比如反光和平鋪紋理.下面的列表描述瞭已知的不能被硬加速支持的繪制操作:

Canvas

clipPath()

clipRegion()

drawPicture()

drawPosText()

drawTextOnPath()

drawVertices()

Paint

setLinearText()

setMaskFilter()

setRasterizer()

 

 

  另外,還有一些操作的行為在啟用硬加速後會變得不一樣:

Canvas

clipRect():異或,差異和反差異剪切都被忽略.3D變換不應用到剪切框中

drawBitmapMesh():顏色數組被忽略

drawLines():反鋸齒不被支持

setDrawFilter():可以設置,但被忽略

Paint

setDither():被忽略

setFilterBitmap():濾鏡一直啟用

setShadowLayer():僅對文本起作用

ComposeShader

ComposeShader隻能包含不同類型的著色器(比如一個BitmapShader和一個LinearGradient,不能是兩個BitmapShader)

ComposeShader不能包含ComposeShader

 

 

  如果你的應用被這些缺少的特性或限制影響瞭,你可以通過調用setLayerType(View.LAYER_TYPE_SOFTWARE,null)為受影響的部分關閉硬加速.用此方法,你依然可以在其它地方享用到硬加速.

 

摘自 nkmnkm的專欄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *