Android群英傳讀書筆記(第十章)
本章主要介紹的是android的性能優化。
## 1.布局優化
* Android UI渲染機制
在Android中,系統通過VSYNC信號出發對UI的渲染、重繪,其間隔時間是16ms。這個16ms其實就是1000ms中顯示60幀畫面的單位時間(玩游戲的就該知道,大于等于60幀就感覺不到卡頓)。Android系統提供了檢測UI渲染時間的工具,打開“開發者選項”,選擇“Profile GPU Rendering”(我的手機是“GPU呈現模式分析”),選中“On screen as bars”(我的為“在屏幕上顯示為條形圖”)。每一條柱狀線都包括三部分,藍色代表測量繪制Display List的時間,紅色代表OpenGL渲染Display List所需要的時間,黃色代表CPU等待GPU處理的時間,中間綠色橫線代表VSYNC時間16ms,需要盡量將所有條形圖都控制在這條綠線之下。
* 避免Overdraw
過渡繪制會浪費很多CPU、GPU資源,例如系統默認會繪制Activity的背景,而如果再給布局繪制了重疊的背景,那么默認Activity的背景就屬于無效的過渡繪制。Android系統在開發者選項中提供了這樣一個檢測工具--“Enable GPU Overdraw”。借助它可以判斷Overdraw的次數。盡量增大藍色的區域,減少紅色的區域。
* 優化布局層級
在Android中系統對View的測量、布局和繪制都是通過遍歷View樹來進行的,如果View樹太高,就會影響其速度,Google也建議View樹的高度不宜超過10層。
* 避免嵌套過多無用布局
* 使用<include>標簽重用Layout:
為了能夠在不同的Layout組件中使用共通UI,就可以通過<include>標簽來完成。
~~~
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:textSize="20sp"
android:text="this is a common ui">
</TextView>
~~~
然后在布局中進行引用:
~~~
<RelativeLayout 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"
tools:context=".MainActivity">
<include
layout="@layout/test"
android:layout_width="100dp"
android:layout_height="50dp" />
</RelativeLayout>
~~~
如果你需要在<include>標簽中覆蓋類似原布局中android:layout_xxxxx屬性,就必須在<include>標簽中同時指定android:layout_width和android:layout_height屬性。
* 使用<ViewStub>實現View的延遲加載
<ViewStub>是個非常輕量級的組件,不僅不可視而且大小為0。這個布局在初始化時不需要顯示,只有在某些情況下才顯示出來。下面是實例代碼:
~~~
<RelativeLayout 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"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="not often use" />
</RelativeLayout>
~~~
使用<ViewStub>:
~~~
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context=".MainActivity">
<ViewStub
android:id="@+id/view_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout="@layout/test" />
</RelativeLayout>
~~~
~~~
ViewStub viewStub= (ViewStub) findViewById(R.id.view_stub);
//下面兩個方法都是用來實現延遲加載的,區別是inflate()方法會返回引用的布局。
viewStub.setVisibility(View.VISIBLE);
View view=viewStub.inflate();
TextView tv= (TextView) view.findViewById(R.id.tv);
~~~
<ViewStub>標簽與設置View.GONE這種方式的區別在于<ViewStub>標簽只在顯示時渲染整個布局,而設置View.GONE這種方式在初始化時就已經加載了,所以相比之下<ViewStub>更有效率。
* Hierarchy Viewer
這是個用來測試布局冗余的工具,具體用法就不做記錄了。介紹在此
## 2.內存優化
* 內存介紹
* 寄存器:速度最快的存儲場所,因為寄存器位于處理器內部,在程序中無法控制。
* 棧:存放基本類型的數據和對象的引用,但對象本身不存放在棧中,而是存放在堆中。
* 堆:堆內存用來存放由new創建的對象和數組,在堆中分配的內存,由Java虛擬機的自動垃圾回收器(GC)來管理。
* 靜態存儲區域:是指在固定的位置存放應用程序運行時一直存在的數據,Java在內存中專門劃分了一個靜態存儲區域來管理一些特殊的數據變量如靜態的數據變量。
* 常量池:就是該類型所用到常量的一個有序集合,包括直接常量(基本類型,String)和對其他類型、字段和方法的符號引用。
* 內存優化實例
* Bitmap優化
Bitmap是造成內存占用過高甚至是OOM的最大威脅,可以通過以下技巧進行優化
① 使用適當分辨率和大小的圖片:例如在圖片列表界面可以使用圖片的縮略圖thumbnails,而在顯示詳細圖片的時候再顯示原圖;或者在對圖像要求不高的地方,盡量降低圖片的精度。
② 及時回收內存:一旦使用完Bitmap后,一定要及時使用bitmap.recycle()方法釋放內存資源。自Android3.0后,由于Bitmap被放到了堆中,其內存由GC管理,就不需要釋放了。
③ 通過內存緩存LruCache和DiskLruCache可以更好地使用Bitmap。
* 代碼優化
任何Java類都將占用大約500字節的內存空間,創建一個類的實例會消耗大約15字節內存。從代碼的實現上,也可以對內存進行優化。
① 對常量使用static修飾符。
② 使用靜態方法,靜態方法會比普通方法提高15%左右的訪問速度。
③ 減少不必要的成員變量,這點在Android Lint工具上已經集成檢測了。
④ 減少不必要對象,使用基礎類型會比使用對象更加節省資源,同時更應該避免頻繁創建短作用域的變量。
⑤ 盡量不要使用枚舉、少用迭代器。
⑥ 對Cursor、Receiver、Sensor、File等對象,要非常注意對它們的創建、回收和注冊、反注冊。
⑦ 避免使用IOC框架,IOC通常使用注解、反射來進行實現,大量使用反射會帶來性能的下降。
⑧ 使用RenderScript、OpenGL來進行非常復雜的繪圖操作。
⑨ 使用SurfaceView來代替View進行大量、頻繁的繪圖操作。
⑩ 盡量使用視圖緩存,而不是每次都執行inflate()解析視圖。
本章節后面還介紹了Lint、MemoryMonitor、TraceView、MAT等工具來分析內存的使用情況,