Android布局性能調(diào)優(yōu)

前言

在Android開發(fā)中,View的展示是最貼近用戶,也是最能直觀展示產(chǎn)品的手段。除了美觀的界面之外,View的性能也是很重要的。

而View是由一層一層的View嵌套而成,形成類似于樹的層級結(jié)構(gòu),通過層級結(jié)構(gòu)展示View。View樹的深度決定了展示的流暢度,深度越深,繪制需要的時間也就越長,體驗效果越差。優(yōu)化布局從另一方面說,也是就是想辦法降低View樹的深度,提高加載速度,達(dá)到性能調(diào)優(yōu)。

下面介紹三個日常開發(fā)中可能會使用到的布局優(yōu)化標(biāo)簽,以及一個實際開發(fā)中可能碰到的問題和解決方式。

代碼比較簡潔有的甚至沒有,但是標(biāo)簽本來就是一些工具而已,把最后實戰(zhàn)方面的看懂了,汲取了這種封裝的思想,我寫這篇文章的目的就達(dá)到了。

include標(biāo)簽

當(dāng)一個View需要復(fù)用的時候,采取<include/>標(biāo)簽可以減少重復(fù)布局的使用。

使用場景

<include/>標(biāo)簽可能接觸的都比較多,在Android布局中,很多時候會碰到需要使用相同的布局,例如每個Activity的TitleBar,評論框等。這個時候可以使用<include/>標(biāo)簽。

步驟

  1. 新建一個title.xml,在里面寫好對應(yīng)的布局文件的實現(xiàn),
  1. 在需要使用的地方使用
other code...

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

ViewStub標(biāo)簽

<ViewStub/>是一種不可見且大小為0的View,它的主要作用是當(dāng)你不需要的時候不加載,當(dāng)你需要的時候才去加載這個布局。也就是說<ViewStub/>實現(xiàn)了View的延遲加載。

需要注意的是:當(dāng)ViewStub設(shè)置為可見或者被inflate之后,就會填充布局資源,之后會被填充的View給替代,和普通的View沒有任何區(qū)別。

使用場景

錯誤圖,也就是當(dāng)數(shù)據(jù)錯誤的時候需要展示的一些圖片和提示信息。但是這個錯誤圖又不是每次都會顯示,大部分情況下都是正常顯示,只有當(dāng)出現(xiàn)一些問題的時候才會顯示錯誤圖,這個時候就可以使用<ViewStub/>

步驟

  1. 在需要使用的地方使用<ViewStub/>標(biāo)簽
<?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" >
 

    <ViewStub
        android:id="@+id/network_error_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout="@layout/network_error"
        android:inflatedId="@+id/error_view"/>
 
</RelativeLayout>

2.新建network_error.xml文件

比如說一個ImageView

other code...

3.代碼中使用

ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
networkErrorView = stub.inflate();

在ViewStub中:

android:layout表示當(dāng)需要展示的時候?qū)故镜腖ayout

android:inflatedId表示當(dāng)在Java代碼中調(diào)用ViewStub的inflate()或者setVisibility()方法返回的Id,也是就填充圖Id。

merge標(biāo)簽

減少View樹深度的利器

使用場景

在一般情況下,比如在ViewPager或者RecyclerView中,我們在每個Item的根布局中往往是使用LinearLayout或者其他的ViewGroup。如果有的時候我們只需要展示一張照片或者單獨文字,這樣就很不值得,因為每個ViewGroup對應(yīng)的就在View樹中又往深了一步。這個時候使用<merge/>標(biāo)簽來減少View樹的深度再好不過。

merge標(biāo)簽可用于兩種典型情況:

  • 布局頂結(jié)點是FrameLayout且不需要設(shè)置background或padding等屬性,可以用merge代替,因為Activity內(nèi)容視圖的parent view就是個FrameLayout,所以可以用merge消除只剩一個。
  • 某布局作為子布局被其他布局include時,使用merge當(dāng)作該布局的頂節(jié)點,這樣在被引入時頂結(jié)點會自動被忽略,而將其子節(jié)點全部合并到主布局中。

步驟

<?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_40"
        android:layout_above="@+id/text"/>
 
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_alignParentBottom="true"
        android:text="@string/app_name" />
 

優(yōu)化實戰(zhàn)例子

需求

在開發(fā)中有的時候TitleBar需要實現(xiàn)各種不同的布局,比如這個Activity需要一個TextView,這個Activity可能需要一個EditText,或者各種自定義View。

這個時候如果每個Activity的TItleBar都對應(yīng)寫新的布局,這樣無疑加大了工作量。

思路(!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)

我們可以將這個TitleBar很Activity邏輯分離,抽出布局作為titlebar.xml,里面包含了各種View。

然后再抽出一個TitleBar.class類,組合放在BaseActivity中。共通的東西可以在BaseActivity實現(xiàn)(比如左前方返回按鈕),不同的東西放在子類中實現(xiàn)(EditText或者自定義View),靈活使用ViewStud實現(xiàn)延遲加載,merge減少層級。

代碼結(jié)構(gòu)可以使用Builder模式實現(xiàn),注意<ViewStub/>和<merge/>的使用,注意空指針以及容錯,這樣就實現(xiàn)了一個標(biāo)準(zhǔn)TitleBar控件。

后話

還有一些很好的工具可以實現(xiàn)布局優(yōu)化,比如Android Studio的lint,TraceView,HierarchyViewer,手機自帶的開發(fā)人員選項中的工具等等等。

規(guī)范的布局代碼加上工具檢測,布局優(yōu)化就OK了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容