天天看點

Android面試題總結(八)優化篇(記憶體優化和UI優化)

1.記憶體洩露和記憶體溢出分别是什麼,他們之間有什麼關系?

記憶體洩露是指儲存了不可能再被通路的變量引用,導緻垃圾回收器無法回收記憶體。

也就是說,在java中有些對象的生命周期是有限的,當他們完成了特定的邏輯後将會被垃圾回收;但是,如果在對象的生命周期本來該被垃圾回收時這個對象還被别的對象所持有引用,那就會導緻記憶體洩露。

記憶體溢出是指虛拟機記憶體耗盡,無法為新對象配置設定記憶體,導緻引用崩潰。典型的情況為加載多張大圖,導緻記憶體耗盡。

2.什麼情況下會導緻記憶體洩露?

(1)資源釋放問題

      程式代碼的問題,長期保持某些資源,如Context,Cursor,IO流的引用,資源得不到釋放造成記憶體洩露。

(2)對象記憶體過大問題

       儲存了多個好用記憶體過大的對象(如Bitmap,xml檔案),造成記憶體超出

(3).static 關鍵字的使用問題

   static是java中的一個關鍵字,當用它來修飾成員變量時候、,那麼改變量就屬于該類,而不是該類的執行個體。是以用static修飾的變量,他的生命周期是很長的,如果用它來引用一些耗費資源過多的執行個體(Context的情況最多),這時候就要謹慎對待了

針對static的解決方案:

   <1>應該盡量避免static成員變量引用耗費過多的執行個體,比如Context。

   <2>Context盡量使用ApplicationContext,因為Application的Context的生命周期比較長,引用它不會出現記憶體洩露的問題。

   <3>使用WeakRefrence代替強引用。比如可以使用WeakRefrence<Context>mContextRef;

(4).線程導緻記憶體溢出

  線程産生記憶體洩露的主要原因在于線程生命周期的不可控。

針對這種線程導緻的記憶體洩露問題的解決方案:

  <1>将線程的内部類,改為靜态内部類(因為費靜态内部類擁有外部類對象的強引用,而靜态類則不擁有)。

   <2>線上程内部采用弱引用儲存Context引用

(5).查詢資料庫沒有關閉cursor

程式中經常會進行查詢資料庫的操作,但是經常會有使用完畢Cursor後沒有關閉的情況。如果我們查詢的結果集比較小,對内訓的消耗不容易被發現,隻有在長時間的大量操作的情況下才最出現記憶體問題,這樣就會給以後的測試和問題排查帶來困難和風險。

(6).構造Adapter沒有複用convertview

在使用ListView的時候通常會使用Adapter,那麼我們應該盡可能呢的使用ConvertView

為什麼要複用convertView?

當convertView為空的時候,用setTag()方法為每個View綁定一個存放空間的ViewHolder對象。當convertView不為空。重複利用已經建立的view的時候,使用getTag()方法擷取綁定的ViewHolder對象,這樣就避免了findViewById對空間的層層查詢,而是快速定位到控件。

(7).Bitmap不再使用時沒有調用recycle()釋放記憶體

     有時候我們會手動的操作Bitmap對象,如果一個Bitmap對象比較占用記憶體,當它不在被使用的時候,可以調用Bitmap.recycle()方法回收此對象的像素所占用的記憶體,但這不是必須的,是情況而定

3.如果對android記憶體進行優化?

 (1)Bitmap OOM(圖檔優化)

     縮放性能優化,緩存性能優化,重用性能優化,PNG壓縮性能優化,選擇性加載優化

  (2)ListView優化

  (3)UI Review(視圖UI優化)

   (4)使用ThreadPool線程池而不是每次new Thread

    (5)String字元串優化

    (6)減少不必要的全局變量

     (7)Cursor(遊标)回收

      (8)Receiver(接收器)回收

       (9)Stream/File(流/檔案)回收

       (10)避免内部getters/Setters

       (11)for循環

4.String字元串優化

最常見的例子就是當你要頻繁操作一個字元串時。使用StringBuffer代替String。

還比如:使用int數組而不是Integer數組。

避免建立短命的臨時對象,減少對象的建立就能減少垃圾收集,進而減少對使用者體驗的影響。

5.UI視圖優化

減少視圖層級,可以有效的減少記憶體消耗,因為視圖是一個樹形結構,每次重新整理和渲染都會周遊一次

(1)ViewStub标簽可以使UI在特殊情況下,隻管效果類似于設定View的不可見性,但是其最大意義在于被整各标簽所包裹的vIEWS在預設狀态下不會占用任何記憶體空間。

(2)Merge

單獨将<merge/>标簽做個介紹,是因為它在優化UI結構時起到很重要的作用。目的是通過删減多餘或者額外的層級,進而優化整個Android Layout結構。核心功能就是減少備援的層次進而達到優化UI的目的

(3)include

可以通過這個标簽直接加載外部的xml到目前結構中,是複用UI資源的常用标簽

(4)盡量使用相對布局

6.ListView優化

(1)Item布局,層級越少越好,使用hierarchyview工具檢視優化

(2)複用convertView

(3)使用ViewHolder

(4)item中有圖檔時,異步加載

(5)快速滑動時,不加載圖檔

(6)item中有圖檔時,應對圖檔進行适當的壓縮

(7)實作資料的分頁加載

7.性能優化工具的使用

MAT,LearkCanary,Memory Monitor,Allocation Tracking,Heap Tool,hierarchyviewer布局檢測工具

第三方分析工具

 MemoryAnalyzer,GT Home,iTest