Android性能優化典範

後期我會面試50家互聯網公司,不斷總結完善和思考,寫出一本完美的安卓面試書籍,大家支持我嗎?

目錄

1、內存優化
2、ui優化
3、網絡優化
4、啓動優化

1、內存優化

1.1、解決所有的內存泄漏

1.1.1、內存泄漏:

堆上分配的對象已經不會再使用,但是GC收集器無法對其進行回收,此對象被強應用所引用 。

1.1.2、GC收集器原理:

可達性算法:從GCRoot對象爲起點,向下搜索,可到達的對象是稱爲GC可達,GC收集器不會回收,不可到達的對象稱爲不GC不可達,是GC收集器回收的對象。

GCRoot對象:
(1)、虛擬機棧(棧幀找那個的局部變量表)中的對象;
(2)、方法區中類靜態變量引用的對象;
(3)、方法區中常量引用的對象。

1.1.3、常見的內存泄漏實例

(1)、單例造成的內存泄漏



單例類的實例是靜態的,如果需要其構造方法需要傳遞一個context,如果傳入的是 Activity 的 Context,當傳入 Activity 就會造成泄漏了。
解決方法:this.context = context.getApplicationContext();// 使用Application 的context。

(2)、內部類造成的內存泄漏



在Activity中有一個內部類,如果創建了這個內部類的靜態對象,Activity關閉的時候,由於內部類會持有外部類的引用,內部類靜態對象會持有外部類Activity的引用,導致Activity發生內存泄漏。
解決方法:將該內部類設爲靜態內部類,如果該內部類需要持有外部類的引用,則使用軟引用/弱引用,在使用外部類的引用之前需進行空判斷。

(3)、異步線程造成的內存泄漏



在Activity中有一個開啓一個線程執行一個runnable,這個runnable是內部類就會持有外部類Activity的引用,如果線程的生命週期比Activity的生命週期長,就不會導致Activity內存泄漏。
解決方法:同上

(4)、Handler 造成的內存泄漏



在Activity中聲明一個內部類handler,當使用這個handler發送一個延遲消息時,此消息執行前,Activity關閉會造成內存泄漏。
解決方法:同上

(5)資源未關閉造成內存泄漏
對於使用了BraodcastReceiver,ContentObserver,File,遊標 Cursor,Stream,Bitmap等資源的使用,應該在Activity銷燬時及時關閉或者註銷,否則這些資源將不會被回收,造成內存泄漏。

1.1.4、內存泄漏檢測方案

LeakCanary原理:

  1. LeakCanary在一個Fragment或者Activity onDestory的時候,創建一個弱引用 KeyedWeakReference 到要被監控的對象。

  2. 然後在後臺線程檢查引用是否被清除,如果沒有,調用GC。

  3. 如果引用還是未被清除,把 heap 內存 dump 到 APP 對應的文件系統中的一個 .hprof 文件中。

  4. 在另外一個進程中的 HeapAnalyzerService 有一個 HeapAnalyzer 使用HAHA 解析這個文件。

  5. 得益於唯一的 reference key, HeapAnalyzer 找到 KeyedWeakReference,定位內存泄露。

  6. HeapAnalyzer 計算 到 GC roots 的最短強引用路徑,並確定是否是泄露。如果是的話,建立導致泄露的引用鏈。

1.2、避免內存抖動

內存抖動代表頻繁GC,會佔用程序執行時間,造成頁面卡頓等性能問題。

1.2.1、避免內存抖動的方式:

(1)、避免在onDraw中創建Paint、Bitmap對象等;
(2)、避免在循環中創建臨時對象;
(3)、避免在scrollListener中創建對象。

1.3、內存抖動檢測方法

(1)、使用Android profiler 進行觀察,如果發下內存劇增劇減則是GC時間,可查看GC時間段的內存,找出重複創建的大量對象,進行優化(例子:在recycleview中獲取距離屏幕的距離時,創建大量對象)。

1.3、圖片優化

(1)、網絡圖片:使用網絡裁剪服務,獲取適當的圖片加載。
(2)、本地圖片:使用Tinypng深度壓縮,必要時進行裁剪。
(3)、使用web格式代替png、jpeg格式。
(4)、使用Fresco對圖片進行管理。

1.3.1、fresco對內存的管理:

(1)、在5.0以下系統,Bitmap緩存位於ashmem,這樣Bitmap對象的創建和釋放將不會引發GC,更少的GC會使你的APP運行得更加流暢。5.0及其以上系統,相比之下,內存管理有了很大改進,所以Bitmap緩存直接位於Java的heap上。
(2)、當應用在後臺運行時,該內存會被清空。

1.4、使用優化的數據結構

2、ui優化

2.1、分析佈局,減少佈局嵌套或者替換消耗性能少的佈局

2.2、使用include+merge減少佈局層級

2.3、使用viewstub提供按需加載

3、網絡優化

3.1、網絡速度:

正常一條網絡請求需要經過的流程是這樣:
(1)、DNS 解析,請求DNS服務器,獲取域名對應的 IP 地址;
(2)、與服務端建立連接,包括 tcp 三次握手,安全協議同步流程;
(3)、連接建立完成,發送和接收數據,解碼數據。

這裏有明顯的三個優化點:

3.1、IP直連或者HTTPDNS;
3.2、開啓 keep-alive進行連接複用;
3.3、減少請求和返回數據的大小;

(1)、請求和返回數據做Gzip壓縮;
(2)、精簡數據格式;
(3)、按需加載圖片(圖片裁剪,也可按網絡狀態返回不同分辨率的圖片);

3.4、數據緩存;

3.2、網絡優化補充:

3.4、請求打包;(如埋點統計)
3.5、協議優化;(如使用優化的的更好的http2,請求頭壓縮)
3.6、斷點續傳。

4、啓動優化

4.1、異步加載一:Application中加入異步線程

4.2、異步加載二:MainActivity中加入異步線程

4.3、 延遲加載功能:首屏繪製完成之後加載

4.4、動態加載佈局:主佈局文件優化

4.5、主佈局文件深度優化

4.6、 功能代碼深度優化

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