【Android】Android性能優化

一、佈局優化


        系統在渲染 UI 的時候會消耗大量資源,所以一個好的佈局不僅要具有好的視覺效果,更應該保有良好的使用體驗。


1. Android UI 渲染機制


        人眼感覺到的動畫流暢畫面,幀數在40幀/秒到60幀/秒。

        Android 中,系統通過 VSYNC 信號觸發對 UI 的渲染、重繪,間隔時間是16ms(1秒中顯示60幀畫面的單位時間)。如若 Android 程序讓系統每次渲染的時間都保持在16ms之內,那麼人們看到的 UI 界面將是非常流暢的。

        如若不能在16ms內完成繪製,那麼就會造成丟幀現象,即當前該重繪的幀被未完成的邏輯阻塞。例如,一次繪製任務耗時20ms,那麼在16ms系統發出 ASYNC 信號時就無法繪製,該幀就被丟棄,必須等待下次信號才繼續開始繪製,導致16*2ms內都是顯示同一幀畫面,這就是畫面卡頓。

        關於 Android 系統的檢測 UI 渲染時間的工具使用,可以在 profile gpu rendering 查看。


2.避免 Overdraw


        Overdraw 即過度繪製,會浪費很多CPU、CPU資源。例如,系統默認會繪製Activity背景,而如果再給佈局繪製了重疊的背景,那麼默認的 Activity 背景就屬於無效的過度繪製。

        Android 系統在開發者選項中提供了檢測工具——“Enable GPU Overdraw”。激活後,可以通過界面上的顏色來判斷 Overdraw 的次數。通過這個工具儘量優化繪圖層次,增大藍色區域,減少紅色區域。


3.優化佈局層級


        在 Android 中系統對 View 進行測量、佈局和繪製時,都是通過對 View 樹的遍歷來進行操作的。如果一個 View 樹高度太高,會嚴重影響測量、佈局和繪製的速度,因此優化佈局的另一個方法就是降低 View 樹的高度。 Google 在 API 文檔中建議 View 樹的高度不宜超過 10 層。

        現在版本的 Android 中, Google 已經默認使用 RelativeLayout 來替代 LinuerLayout 作爲默認根佈局,原因是通過扁平的 Relative Layout 來降低通過 Linear Layout 嵌套所產生布局樹的高度,從而提高 UI 渲染效率。


4.避免嵌套過多無用佈局


        嵌套的佈局會讓 View 樹的高度越來越高,因此在佈局時,要根據自身佈局特點選擇不同的 Layout 組件,從而避免通過某一種不適當的 Layout 組件來實現功能時的侷限性,造成嵌套過多的現象。


4.1.使用<include>標籤重用 Layout


        通過<include>標籤定義一個共同 UI 組件,可以避免代碼的冗長和重複率,方便閱讀。

        例如,要寫一個共通的 Text View,可以在一個單獨的 xml 文件中描述出來,並將 layout_width 和 layout_height 設置爲 0dp,迫使開發者在使用時對寬高進行賦值,否則將無法看到這個組件,然後在引用的時候再重新爲通用組件的寬高賦值。


4.2.使用<ViewStub>實現 View 的延遲加載


        ViewStub 在 UI 初始可見時不會顯示,必須通過 mViewStub.setVisibility(View.VISIBLE); 或者 View inflateView = mViewStub.inflate(); 來顯示佈局,只有在顯示的時候纔會開始渲染。


二、內存優化


1.什麼是內存


        由於 Android 應用的沙箱機制,每個應用所分配到的內存大小是有限度的,內存太低就會觸發 LMK——Low Memory Killer 機制。

  • 寄存器(Registers)

        速度最快的存儲場所,寄存器位於處理器內部,在程序中無法控制。

  • 棧(Stack)

        存放基本類型的數據和對象的引用,但對象本身不存放在棧中,而是存放在堆中。

  • 堆(Heap)

        堆內存用來存放由 new 創建的對象和數組。在堆中分配的內存,由 Java 虛擬機的自動垃圾回收器(GC)來管理。

  • 靜態存儲區域(Static Field)

        靜態存儲區域就是指在固定的位置存放應用程序運行時一直存在的數據,Java 在內存中專門劃分了一個靜態存儲區域來管理一些特殊的數據變量如靜態數據變量。

  • 常量池(Constant Pool)

        JVM 虛擬機必須爲每個被裝載的類型維護一個常量池。常量池就是該類型所用到常量的一個有序集合,包括直接常量(基本類型,String)和對其他類型、字段和方法的符號引用。


        關於棧和堆的概念

        棧存放基本數據類型(byte、short、int、long、float、double、boolean、char)和對象句柄,對於數字常量和字符串常量可以共享數據,對於堆來說棧分配資源速度快,當指定的某變量作用域結束後,這部分內存空間會馬上被用作新的空間進行分配;

        堆是存放類類型、由 new 建立的對象內存空間。當對象的作用域結束後,這部分內存不會立即被回收,而是等待垃圾自動回收機制負責回收,回收速度慢。

        String  heapStr = new String("Lu"); //heapStr 存放在棧裏,字符串 “Lu” 存放在堆內存

        String stackStr = "Lu"; //stackStr存放在棧裏,字符串 “Lu” 存放在常量池中


2.內存優化


2.1.Bitmap 優化


  • 使用適當分辨率和大小的圖片
        由於 Android 系統在做資源適配的時候會對不同分辨率文件夾下的圖片進行縮放來適配相應的分辨率,如果圖片分辨率與資源文件夾分辨率不匹配或者圖片分辨率太高,就會導致系統消耗更多內存資源。同時,在適當的時候,應該顯示合適大小的圖片,例如在圖片列表界面可以使用圖片的縮略圖 thumbnails,而在顯示詳細圖片的時候再顯示原圖;或者在對圖像要求不高的地方,儘量降低圖片的精度。
  • 即使回收內存
        使用完 Bitmap 之後及時調用 bitmap.recycle() 方法釋放內存資源。自 Android 3.0 之後, Bitmap 被放置在堆中,其內存由 GC 管理,就不再需要手動進行釋放了。
  • 使用圖片緩存

        通過內存緩存(LruCache)和硬盤緩存(DiskLruCache)可以更好地使用 Bitmap。


2.2.代碼優化


        任何 Java 類都佔用大約 500 字節的內存空間。創建一個實例大約消耗 15 字節的內存。

  • 對常量使用 static 修飾符
  • 使用靜態方法,會比普通方法提高 15% 左右的訪問速度
  • 減少不必要的成員變量,如果一個變量可以定義爲局部變量,則儘量不要定義爲成員變量
  • 減少不必要的對象,使用基礎類型會更加節省資源,同時儘量避免創建短作用域的變量
  • 儘量不要使用枚舉、迭代器
  • 對 Cursor、Receiver、Sersor、File、IO、網絡連接等,要及時回收,關閉或者解註冊
  • 避免使用 IOC 框架, IOC 通常使用註解、反射來實現
  • 使用 RenderScript、OpenGL 進行復雜的繪圖操作
  • 使用 SurfaceView 來替代 View 進行大量、頻繁的繪圖操作
  • 儘量使用視圖緩存,而不是每次都執行 inflate() 解析視圖


2.3.內存泄露、內存溢出以及避免


詳情見:http://blog.csdn.net/sko121/article/details/77747851

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