1. 程式人生 > >android 繪製過程摘要

android 繪製過程摘要

1、沒有硬體加速的UI繪製過程:在Android應用程式程序這一側,每一個視窗都關聯有一個Surface。每當視窗需要繪製UI時,就會呼叫其關聯的Surface的成員函式lock獲得一個Canvas,其本質上是向SurfaceFlinger服務Dequeue一個Graphic Buffer。Canvas封裝了由Skia提供的2D UI繪製介面,並且都是在前面獲得的Graphic Buffer上面進行繪製的。繪製完成之後,Android應用程式程序再呼叫前面獲得的Canvas的成員函式unlockAndPost請求顯示在螢幕中,其本質上是向SurfaceFlinger服務Queue一個Graphic Buffer,以便SurfaceFlinger服務可以對Graphic Buffer的內容進行合成,以及顯示到螢幕上去。

2、有硬體加速的UI繪製過程:硬體加速渲染和軟體渲染一樣,在開始渲染之前,都是要先向SurfaceFlinger服務Dequeue一個Graphic Buffer。不過對硬體加速渲染來說,這個Graphic Buffer會被封裝成一個ANativeWindow,並且傳遞給Open GL進行硬體加速渲染環境初始化。在Android系統中,ANativeWindow和Surface可以是認為等價的,只不過是ANativeWindow常用於Native層中,而Surface常用於Java層中。另外,我們還可以將ANativeWindow和Surface看作是像Skia和Open GL這樣圖形渲染庫與作業系統底層的圖形系統建立連線的一個橋樑。

       Open GL獲得了一個ANativeWindow,並且進行了硬體加速渲染環境初始化工作之後,Android應用程式就可以呼叫Open GL提供的API進行UI繪製了,繪製出來內容就儲存在前面獲得的Graphic Buffer中。當繪製完畢,Android應用程式再呼叫libegl庫提供的一個eglSwapBuffer介面請求將繪製好的UI顯示到螢幕中,其本質上與軟體渲染過程是一樣的,都是向SurfaceFlinger服務Queue一個Graphic Buffer,以便SurfaceFlinger服務可以對Graphic Buffer的內容進行合成,以及顯示到螢幕上去。

3、繪製提速辦法:在Android應用程式視窗中,每一個View都抽象為一個Render Node,而且如果一個View設定有Background,這個Background也被抽象為一個Render Node。這是由於在OpenGLRenderer庫中,並沒有View的概念,所有的一切可繪製的元素都抽象為一個Render Node。

       每一個Render Node都關聯有一個Display List Renderer。這裡又涉及到另外一個概念——Display List。注意,這個Display List不是Open GL裡面的Display List,不過它們在概念上是差不多的。Display List是一個繪製命令緩衝區。也就是說,當View的成員函式onDraw被呼叫時,我們呼叫通過引數傳遞進來的Canvas的drawXXX成員函式繪製圖形時,我們實際上只是將對應的繪製命令以及引數儲存在一個Display List中。接下來再通過Display List Renderer執行這個Display List的命令,這個過程稱為Display List Replay。

       引進Display List的概念有什麼好處呢?主要是兩個好處。第一個好處是在下一幀繪製中,如果一個View的內容不需要更新,那麼就不用重建它的Display List,也就是不需要呼叫它的onDraw成員函式。第二個好處是在下一幀中,如果一個View僅僅是一些簡單的屬性發生變化,例如位置和Alpha值發生變化,那麼也無需要重建它的Display List,只需要在上一次建立的Display List中修改一下對應的屬性就可以了,這也意味著不需要呼叫它的onDraw成員函式。這兩個好處使用在繪製應用程式視窗的一幀時,省去很多應用程式程式碼的執行,也就是大大地節省了CPU的執行時間。

4、執行緒:在Android 5.0之前,Android應用程式的Main Thread不僅負責渲染UI,還負責處理使用者輸入。通過引進Render Thread,我們就可以將UI渲染工作從Main Thread釋放出來,交由Render Thread來處理,從而也使得Main Thread可以更專注高效地處理使用者輸入,這樣使得在提高UI繪製效率的同時,也使得UI具有更高的響應性。

5、OPENGL 繪製環境初始化:Open GL環境也稱為Open GL渲染上下文。一個Open GL渲染上下文只能與一個執行緒關聯。在一個Open GL渲染上下文建立的Open GL物件一般來說只能在關聯的Open GL執行緒中操作。這樣就可以避免發生多執行緒併發訪問發生的衝突問題。這與大多數的UI架構限制UI操作只能發生在UI執行緒的原理是差不多的。Render Thread有一個Task Queue,Main Thread通過一個代理物件Render Proxy向這個Task Queue傳送一個drawFrame命令,從而驅使Render Thread執行一次渲染操作。因此,Android應用程式UI硬體加速渲染環境的初始化過程任務之一就是要建立一個Render Thread。 一個Android應用程式可能存在多個Activity元件。在Android系統中,每一個Activity元件都是一個獨立渲染的視窗。由於一個Android應用程式只有一個Render Thread,因此當Main Thread向Render Thread發出渲染命令時,Render Thread要知道當前要渲染的視窗是什麼。從這個角度看,Android應用程式UI硬體加速渲染環境的初始化過程任務之二就是要告訴Render Thread當前要渲染的視窗是什麼。