Android中View繪制優化之一—- 優化佈局層次

                            譯序

 

 

 

         最近一直在做鎖屏界面,之前也寫過關於鎖屏界面的一些簡單原理,未曾想自己真正去深入理解鎖屏時,才

  發覺鎖屏框架真是又大又復雜,主要體現在如下兩個方面:

 

            1、界面的組成以及更新機制;

            2、對電源管理的控制,在鎖屏界面會禁用系統的電源管理,自己接管屏幕亮度的控制。

 

       當然還有更多的邏輯細節處理,隻能耐著性子去研究瞭。。

 

       通過對本次鎖屏界面的處理,才發現自己對View繪制還是不熟透,很多東西也沒有去潛心研究,導致自己在

  真正做項目時候才手忙腳亂的。因此,借著這次機會,也把Android 4.0 developer這些先進的知識(山人一直

 沉浸在Android 2.2中)給過瞭一下,真是妙處多多。

 

 

    開頭: 為瞭避免歧義,先將Android “Layout”一次的意思進行說明,主要有如下三個方面:

                   1、統稱,即如何擺放UI,UI呈現效果等;

                   2、佈局文件  ,即/res/layout/xxx.xml  ;

                   3、佈局過程  ,Android繪制過程中的 layout過程;

                   4、一些佈局控件,例如LinearLayout、FrameLayout等 ;

 

 

 

  正文:

 

                                改善佈局效率(Layout Performace)
 

  

 

         佈局是Android應用程序重要的一部分,它與用戶體驗有著直接聯系。如果一個佈局是糟糕的,它將產生一個

  消耗內存與低效UI應用程序。 Android SDK 及它包含的工具都能幫助你定位在佈局過程中隱藏的問題,通過對

  這些課程的學習,你能夠以很小的內存代價去實現流暢的平滑界面。

 

  課程如下:

 

  1 、優化佈局層次

            同樣地,一個復雜的網頁會延長加載時間,你的佈局層次如果太復雜也能引發一些效率問題。本課程

      告知你如何利用 SDK的工具去觀察你的佈局以及發現佈局過程的瓶頸問題。

 

  2、使用<include />標簽復用佈局文件

            如果應用程序的UI在多處重復某些佈局結構,本課程向你展示如何創建高效、可重用的佈局結構,然後

      以合適的 UI佈局文件包含它們。

              

  3、按需加載View視圖

           除瞭簡單地在另外的佈局文件中包括一個佈局組件,你可能想在需要的時候才將視圖顯現出來,有的時候

     是在Activity運行之後。本課程告訴你如何改進佈局初始化行為—- 按需加載佈局文件的某個視圖。

                 

 4、如何使ListView流暢滑動

          如果你構建瞭一個ListView實例呈現那些包含復雜或者大容量數據的列表項,這可能會影響ListView的流暢

     滑動。本課程提供瞭一些如何讓滑動過程更加流暢的建議。

                 

               

   譯一 :

 

                                     優化佈局層次
 

 

  

         一個通常的錯誤觀念就是使用基本的佈局結構(例如:LinearLayout、FrameLayout等)能夠在大多數情況下

   產生高效率 的佈局。 顯然,你的應用程序裡添加的每一個控件和每一個佈局都需要初始化、佈局(layout)、

   繪制 (drawing)。舉例來說:嵌入一個LinearLayout會產生一個太深的佈局層次。更嚴重的是,嵌入幾個使

   用 layout_weight屬性的LinearLayout 將會導致大量的開銷,因為每個子視圖都需要被測量兩次。這是反復解析

   佈局文件時重要的一點,例如在ListView或者GridView中使用時。

 

 觀察你的佈局
 

     Android SDK 工具箱包括一個稱作“ Hierarchy Viewer”的工具,它允許你去在你的應用程序運行時分析

  佈局。通過使用這個工具,能幫助你發現你的佈局效率上的瓶頸問題。

 

     “ Hierarchy Viewer”工具允許你在已連接的設備或模擬器中選擇正在運行的進程,然後呈現出佈局層次樹

   (layout tree)。每個正方塊下的交通燈(見下圖) — 紅綠藍表現出瞭在測量(measure)、佈局(layout)、以及繪制

   (draw)過程中的效率值,這能幫助你定位潛在的問題。

 

        假設ListView 中的一項Item 存在如下(見圖 1)佈局 :

 

                                

                                        圖1:ListView某項Item的佈局效果圖

 

     “Hierarchy Viewer”工具可以在 <sdk>/tools路徑下找到。當打開它時,“ Hierarchy Viewer”工具顯示瞭

   所有可用的設備以及運行在這些設備上的進程。點擊”Load View Hierarchy”來顯示某個你選擇的組件的UI佈局

  層次。舉例來說,圖2展現瞭圖1的佈局層次樹。

 


                            

                                           圖2:使用LinearLayout的佈局樹

 

      在圖2中,你可以直觀看到這個三層的佈局結構是存在一些問題的。點擊項體現出瞭在每個測量(measure)、

    佈局(layout)、以及繪制(draw)過程中的時間消耗(見圖3)。很明顯,該項(LinearLayout)花費瞭最長的時間去

    測量、佈局、繪制,你應該花點精力去優化它們。

 

                                                         

                                                      圖3: 某個LinearLayout的繪制時間

 

     完成該佈局文件渲染的時間分別為:

                測量過程:0.977ms

                佈局過程: 0.167ms

                繪制過程:2.717ms

 

 修改佈局文件
 

       由於上圖中佈局效率的低下是因為一個內嵌的 LinearLayout控件,通過扁平化佈局文件—-讓佈局變得

  更淺更寬,而不是變得更窄更深層次 ,這樣就能提升效率瞭。 一個RelativeLayout 作為根節點也能提供如上

  的佈局效果(即圖1)。 因此,  使用RelativeLayout 改變佈局的設計,你可以看到現在我們的佈局層次隻有2層瞭。

  新的佈局層次樹如下:

 


                        

                                    圖4:使用RelativeLayout的佈局樹

 

         現在,完成該佈局文件渲染的時間分別為:

                      測量過程:0.977ms

                      佈局過程:0.167ms

                      繪制過程:2.717ms

  

      也許它隻是一點點微小的改進,但這次它會被多次調用,因為是ListView會佈局所有的Item,累積起來,

 改進後效果還是非常可觀地。

 

      大部分的時間差異是由於使用瞭帶有layout_weight 屬性的LinearLayout ,它能減緩測量過程的速度。這僅僅

 是一個例子,即每個佈局都應該合適地被使用以及你應該認真考慮是否有必要采用“layout_weight" 屬性。

 

 使用Lint工具 (譯者註:ADT插件更新到最新的16.0後的工具)

 

       關於Lint的使用更多請看:《Android Lint(官方代碼優化利器)》

    

        一個好的實踐就是在你的佈局文件中使用Lint工具去尋求可能優化佈局層次的方法。Lint已經取代瞭Layoutopt

  工具並且它提供瞭更強大的功能。一些Lint規則如下:

 

  1、使用組合控件 — 包含瞭一個  ImageView 以及一個 TextView 控件的 LinearLayout 如果能夠作為一個

     組合控件將會被更有效的處理。

          2、合並作為根節點的幀佈局(Framelayout)  —-如果一個幀佈局時佈局文件中的根節點,而且它沒有背景圖片

  或者padding等,更有效的方式是使用<merge />標簽替換該< Framelayout />標簽 。

 

          關於這點,更多請看 : <<android merge之佈局>>

                                                    <<Android裡merge和include標簽的使用>>

                                       

 3、無用的葉子節點—– 通常來說如果一個佈局控件沒有子視圖或者背景圖片,那麼該佈局控件時可以被移除

       (由於它處於 invisible狀態)。

 

 4、無用的父節點 —–  如果一個父視圖即有子視圖,但沒有兄弟視圖節點,該視圖不是ScrollView控件或者

    根節點,並且它沒有背景圖片,也是可以被移除的,移除之後,該父視圖的所有子視圖都直接遷移至之前父視圖

    的佈局層次。同樣能夠使解析佈局以及佈局層次更有效。

 

 5、過深的佈局層次  —-內嵌過多的佈局總是低效率地。考慮使用一些扁平的佈局控件,例如 RelativeLayout、

      GridLayout ,來改善佈局過程。默認最大的佈局深度為10 。

 

 

     當使用Eclipse環境開發時,Lint能夠自動解決一些問題,提供一些建議以及直接跳轉到出錯的代碼中去核查。

  如果你沒有使用Eclipse,Lint也可以通過命令行的方式運行。更多關於Lint的可用信息請參看:《Android Lint》 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。