android UI的優化
一、瞭解View的繪製過程
首先我們要了解android的View的繪製的過程:
android的view是一個樹形的結構,從根view也就是DecorView開始,其下面是ViewGroup以及其他的子View,在view繪製的時候,遍歷每一個子節點,同時調用相應的方法。
Android中View繪製流程以及invalidate()等相關方法分析
當我們對UI的繪製過程有所瞭解後我們纔會找到一些寫代碼過程中需要優化注意的地方。
二、UI佈局文件的優化
1、減少佈局的層次;
2、去除不用的佈局或者是累贅的的父控件;
3、使用include,merge,ViewStub 標籤
4、用RelativeLayout代替LinearLayout
例如:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.heraracky.MainActivity"
tools:ignore="MergeRootFrame" >
<LinearLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:orientation="vertical"
android:background="@android:color/darker_gray">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="textView"/>
</LinearLayout>
</FrameLayout>
當我們在佈局的時候要儘可能少的減少子ViewGroup以及子View的個數。紅色框的Framlayout就是多餘的層,這樣會白白的消耗資源。
佈局修改之後:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.heraracky.MainActivity"
tools:ignore="MergeRootFrame" >
<LinearLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:orientation="vertical"
android:background="@android:color/darker_gray">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="textView"/>
</LinearLayout>
</merge>
通過使用merge標籤我們就減少了一層。在這個場合適合使用merge標籤來替代Framlayout,但是如果是LinnearLayout的話就不行了。
有關merge標籤的使用的話請看android merge標籤的使用
此外我們還可以使用ViewStub標籤來減少佈局的層,如果你的佈局不會變化,而且會根據某些狀態來判斷顯示這個佈局還是那個佈局。這時候我們就可以用ViewStub標籤,ViewStub標籤不會被加載,相當於是0,資源零消耗。
ViewStub的用法請看《Android實戰技巧:ViewStub的應用》
三、背景的優化
Activity在啓動的時候會涉及到
Drawing(繪製的刷新率)
Startup Time (啓動Activities的時間)
以上兩個性能的優化都將依賴於 Window backGround drawable功能設置。
通過Window backGround標識會對部分人產生一定的誤解,其實每次通過setContentView()來顯示預先配置的界面時,Android僅僅是將你所創建的Views添加到Activiy的Window中。而且這個Window並不僅僅包含你所創建的Views,還包括Android爲Activity預置的元素。通過Emulator運行你的程序,然後通過Hierarchy Viewer查看當前程序UI架構Root節點 DecorView,這個是Android額外添加的最頂層的節點。
實際上Window background drawable是由DecorView決定的。可以在Activity中調用getWindow().setBackgroundDrawable()方法來設置DecorView的background
drawable。這裏要特別注意這個方法是針對當前版本的Android平臺,以後可能會因爲版本的更新或不同的硬件設備而改變。(目前我們僅針對 G1,如果在其它環境下測試需要小心驗證)
如果目前正在使用android默認的標準Themes,那麼在調用getWindow().setBackgroundDrawable()方法之後,這個background drawable將會影響你的activities。
通過一個例子來直觀的比較性能提升的效果:
我們在設定theme的時候會paint一個background,而現在的根目錄Framlayout也有一個background而且是全屏的覆蓋住DecorView的背景,所以background drawable佔用了不必要的計算資源造成資源的浪費。
下面我們新建一個Theme
創建res/values/theme.xml, XML的內容:
Xml代碼
<resources>
<style name="Theme.NoBackground" parent="android:Theme">
<item name="android:windowBackground">@null</item>
</style>
</resources>
同時也需要修改AndroidMainfest.xml文件,將上邊所創建的Theme應用到Activity中,格式爲:Xml代碼
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".EggImageViewer"
android:label="@string/app_name"
android:theme="@style/Theme.NoBackground">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
這樣DecorView就不會再加載背景,性能上會有所提高。
我們還可以這樣做,效果更佳。就是在Theme中設置背景,在佈局文件中去掉背景,這樣在Activity加載的時候直接就加載了背景,
創建 res/drawable/background_res.xml
Xml代碼
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/shelf_panel"
android:tileMode="repeat" />
創建res/values/theme.xml
Xml代碼
<resources>
<style name="Theme.Shelves" parent="android:Theme">
<item name="android:windowBackground">@drawable/background_res</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
這樣Activity在加載的時候,加載的時間就會縮短。
四、資源背景圖片
NinePatch圖片節省內存,一個小的圖片就可以滿足一個大的背景
五、經常變化的控件要自定義
比如:UI中有時鐘的話,時鐘每一秒鐘都會跟新一次,我們不能用View的invalidate方法和postInvalidate方法更新,這樣的話屏幕中所有的UI控件都會從新繪製,這樣會造成極大的性能問題。我們要局部更新,只更新顯示時間的控件。
所以我們要自定控件來實現。