直播平臺搭建探索App性能優化之佈局優化

一、頁面佈局對App性能的影響和原因
佈局性能主要影響 :App的頁面顯示速度。
佈局影響性能的實質:頁面的測量 & 繪製時間,一個頁面通過遞歸完成測量 & 繪製過程。
二、優化思路
合理的佈局性能、佈局層級、佈局複用性 和 按需加載(測量&繪製時間)。
在佈局優化中,Android的官方提到了這三種標籤、、,下面也是簡單說一下它們的優勢,以及怎麼使用。
三、具體方案
(一) 提高佈局的複用性
1、作用:提取佈局間的公共部分,通過提高佈局的複用性從而減少測量 & 繪製時間。
2、使用:

<include layout="@layout/titlebar"/>

<TextView 
   android:layout_width=”match_parent”
   android:layout_height="wrap_content"
   android:text="@string/Hello World"
   android:padding="10dp" />
3、特別注意: (1)include標籤可以使用單獨的layout屬性,這個也是必須使用的。 (2)include標籤若指定了id屬性,而layout也定義了id,則layout的id會被覆蓋。

(二) 減少視圖層級
1、作用:減少佈局層級,配合include標籤使用,可優化加載佈局文件時的資源消耗。
2、使用:
merge標籤在UI的結構優化中起着非常重要的作用,它可以刪減多餘的層級,優化UI。merge多用於替換FrameLayout或者當一個佈局包含另一個時,merge標籤消除視圖層次結構中多餘的視圖組。
例如:你的主佈局文件是相對佈局,引入了一個相對佈局的include,這時include佈局使用的RelativeLayout就沒意義了,反而減慢UI渲染。這時可以使用merge標籤優化。

//佈局A:layout_a.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_10"/>
    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_heig

ht="@dimen/dp_10"/>

//佈局B:layout_b.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/Button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="@dimen/dp_10" />
        
    <include layout="@layout/layout_a.xml" />
</RelativeLayout>

複製代碼在上述例子,在佈局B中通過標籤引用佈局A,

此時B佈局層級爲 =  RelativeLayout ->> Button
                                   —>> RelativeLayout 
                                            ->> Button
                                            ->> TextView

複製代碼現在使用merge優化,將被引用佈局A根標籤的RelativeLayout改爲merge。那麼在引用佈局A時,佈局A中的merge標籤內容根節點RelativeLayout會被去掉,在include標籤裏存放的是佈局A中的merge標籤爲根節點的子節點即include裏存放的是:ButttonTextView

 此時B佈局層級爲 =  RelativeLayout ->> Button 
                                 ->> Button
                                 ->> TextView

複製代碼即已去掉之前無意義且多餘的,

//佈局A:layout_a.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_10"/>
    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_10"/>
</merge>

(三) 按需加載
1、作用:按需加載 外部引入的佈局,注:屬輕量級View、不佔用顯示 & 位置。
標籤最大的優點是當你需要時纔會加載,使用它並不會影響UI初始化時的性能。各種不常用的佈局想進度條、顯示錯誤消息等可以使用標籤,以減少內存使用量,加快渲染速度。是一個不可見的,大小爲0的View。

2、使用:

    // 步驟1、先設置好預顯示的佈局
    // 步驟2、在其他佈局通過<ViewStub>標籤引入外部佈局(類似<include>)
                注:此時該佈局還未被加載顯示。
    // 步驟3、只有當ViewStub被設置爲可見ViewStub.setVisibility(View.VISIBLE)或者
                調用ViewStub.inflate()時,ViewStub所指向的佈局文件纔會被inflate、
                    實例化,最終 顯示<ViewStub>指向的佈局。

   /** 
     * 實例說明:在佈局A中引入佈局B,只有在特定時刻C中才顯示
     */  
     // 步驟1:先設置好預顯示的佈局B = layout_b.xml
     <?xml version="1.0" encoding="utf-8"?>
     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_10"/>
        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_10"/>
    </RelativeLayout>

    // 步驟2:在佈局A通過<ViewStub>標籤引入佈局B(類似<include>);注:此時該佈局還未被加載顯示
    // 佈局A:layout_a.xml
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <Button
            android:id="@+id/Button"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="@dimen/dp_10" />
        <ViewStub
            android:id="@+id/Blayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout="@layout/layout_b" />
    </RelativeLayout>

    // 步驟3:
    只有當ViewStub被設置爲可見 / 調用了ViewStub.inflate()時,ViewStub所指向的佈局文件
        纔會被inflate 、實例化,最終 顯示<ViewStub>指向的佈局
    ViewStub stub = (ViewStub) findViewById(R.id.Blayout);   
    stub.setVisibility(View.VISIBLE);
    //or
    stub.inflate();

3、特別注意:
(1) ViewStub中的layout佈局不能使用merge標籤,否則會報錯。
(2)ViewStub的inflate只能執行一次,顯示了之後,就不能再使用ViewStub控制它了。
(3)與View.setVisible(View.Gone)的區別:

共同點:初始時不會顯示

不同點:ViewStub標籤只會在顯示時,纔會渲染整個佈局。View.GONE在初始化佈局樹的時候就已經添加在佈局樹上了。相比之下ViewStub標籤節省佈局文件的解析時間和內存的佔用,從而具有更高的效率。

(四) 選擇耗費性能較少的佈局
1、性能耗費低的佈局 = 功能簡單 = LinearLayout、FrameLayout
2、性能耗費高的佈局 = 功能複雜 = RelativeLayout,即佈局過程需消耗更多性能(CPU資源 & 時間)
3、嵌套多個佈局所耗費的性能 > 單個佈局本身耗費的性能,即完成需求時:寧選擇單個耗費性能高的佈局,也不採用嵌套多個耗費性能低的佈局。
4、通過合理選擇佈局類型,從而減少嵌套。即:完成複雜的UI效果時,儘可能選擇1個功能複雜的佈局(如RelativeLayout)完成,而不要選擇多個功能簡單的佈局(如LinerLayout)通過嵌套完成。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章