Android佈局優化

Android佈局優化


Android的UI渲染機制


以前的彩色電視機,它的標準是每秒50幀畫面,看上去非常的流暢。其實人眼感覺到的流暢的畫面,需要每秒40–60幀畫面。在android中,系統通過VSYNC信號觸發對UI的渲染/重繪,UI重繪的時間是16ms,即1000ms/60幀。畫面的卡頓就是丟幀,邏輯阻塞造成重繪未完成。

在Android開發者選項當中,選擇GPU呈現模式分析,並選中在屏幕上顯示爲條線狀,如下圖所示:
這裏寫圖片描述
每一條包含三個部分,最底部的藍色是測量繪製的Display List的時間,上面紅色代表OpenGL渲染Display List所需要的時間,在上面黃色CPU等待GPU的時間。最後的那條綠色橫線是系統VSYNC時間16ms,儘量所有的條形試圖都控制在這條綠色橫線之下。

避免OverDraw


過度繪製浪費很多的CPU/GPU資源,Android系統開發者選項中調試GPU過度繪製,並選中顯示過度繪製區域(PS:只有android4.2及以上的版本才具備此功能)

這裏寫圖片描述

  1. 顏色標識: 從好到差:藍-綠-淡紅-紅

    1. 藍色1x過度繪製
    2. 綠色2x過度繪製
    3. 淡紅色3x過度繪製
    4. 紅色超過4x過度繪製
  2. 驗收標準:

    1. 控制過度繪製爲2x
    2. 不允許存在4x過度繪製
    3. 不允許存在面積超過屏幕1/4區域的3x過度繪製(淡紅色區域)

避免過度繪製的方法:
1. 在佈局層次一樣的情況下, 建議使用LinearLayout代替RelativeLayout, 因爲LinearLayout性能要稍高一點.
2. 在完成相對較複雜的佈局時,建議使用RelativeLayout,RelativeLayout可以簡單實現LinearLayout嵌套才能實現的佈局.
3. 將可複用的組件抽取出來並通過include標籤使用;
4. 使用ViewStub標籤來加載一些不常用的佈局;
5. 動態地inflation view性能要比SetVisiblity性能要好.當然用VIewStub是最好的選擇.
6. 使用merge標籤減少佈局的嵌套層次
7. 去掉多餘的背景顏色
8. 對於有多層背景顏色的Layout來說,留最上面一層的顏色即可,其他底層的顏色都可以去掉
9. 對於使用Selector當背景的Layout(比如ListView的Item,會使用Selector來標記點擊,選擇等不同的狀態),可以將normal狀態的color設置爲”@android:color/transparent”,來解決對應的問題
10. 內嵌使用包含layout_weight屬性的LinearLayout會在繪製時花費昂貴的系統資源,因爲每一個子組件都需要被測量兩次。在使用ListView與GridView的時候,這個問題顯的尤其重要,因爲子組件會重複被創建.所以要儘量避免使用Layout_weight
11. 使得Layout寬而淺,而不是窄而深(在Hierarchy Viewer的Tree視圖裏面體現)

佈局優化


佈局優化的思想很簡單,就是儘量減少佈局文件的層級,佈局層級少了,自然繪製的時間就短了。
另外的一種方案就是採用用include標籤/merge標籤和ViewStub。

  • include標籤來重用layout代碼,可以將一個指定的文件加載到當前的佈局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/all_bg"
    android:clipChildren="false"
    tools:context="com.centraltide.tv.suixin.MainActivity">
    <RelativeLayout
        android:layout_weight="17"
        android:layout_width="match_parent"
        android:layout_height="0dp">
        <include
            android:id="@+id/rlTitle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            layout="@layout/activity_base_title_layout"
            />
        <ImageView
            android:id="@+id/ivMessage"
            android:layout_width="wrap_content"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:layout_centerHorizontal="true"
            android:layout_height="wrap_content" />
        ...
    </RelativeLayout>
</LinearLayout>

在include標籤只支持android:layout_*開頭的屬性,android:id這是個特例

  • 減少視圖層級merge
    merge標籤在UI的結構優化中起着非常重要的作用,它可以刪減多餘的層級,優化UI。merge多用於替換FrameLayout或者當一個佈局包含另一個時,merge標籤消除視圖層次結構中多餘的視圖組。例如你的主佈局文件是垂直佈局,引入了一個垂直佈局的include,這是如果include佈局使用的LinearLayout就沒意義了,使用的話反而減慢你的UI表現。這時可以使用merge標籤優化。
<merge xmlns:android="http://schemas.android.com/apk/res/android">  

    <Button  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content"  
        android:text="@string/add"/>  

    <Button  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content"  
        android:text="@string/delete"/>  

</merge>  

現在,當你添加該佈局文件時(使用include標籤),系統忽略merge節點並且直接添加兩個Button。

  • ViewStub
    ViewStub繼承至View,它非常輕量級且寬高都是0,因此它不參與任何的佈局和繪製。在實際開發中,很多佈局文件正常情況下不會顯示,沒有必要再整個界面初始化的時候加載進來,使用他並不會影響UI初始化時的性能。各種不常用的佈局想進度條、顯示錯誤消息等可以使用ViewStub 標籤,以減少內存使用量,加快渲染速度。通過ViewStub就可以做到在使用的時候在加載。
 <ViewStub  
    android:id="@+id/stub_import"  
    android:inflatedId="@+id/panel_import"  
    android:layout="@layout/progress_overlay"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:layout_gravity="bottom" />

當你想加載佈局時,可以使用下面其中一種方法:

((ViewStub)findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);  
// or  
View importPanel = ((ViewStub)findViewById(R.id.stub_import)).inflate();  

當調用inflate()函數的時候,ViewStub被引用的資源替代,並且返回引用的view。 這樣程序可以直接得到引用的view而不用再次調用函數findViewById()來查找了。
注:ViewStub目前有個缺陷就是還不支持merge標籤。

            今天多一份拼搏、明天多幾份歡笑。tks
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章