這可能是最好的效能優化教程(一)

nanchen2251發表於2017-09-12

這可能是最好的效能優化教程系列專欄
這可能是最好的效能優化教程(一)
這可能是最好的效能優化教程(二)
這可能是最好的效能優化教程(三)

前言

效能檢測與分析,一直在 APP 開發中相當重要,但又被我們常常忽略。很多 APP 或者開發者總是急功近利,總想著快速充實 APP 的相關功能,把開發進度放在首位沒有問題,可很多時候就沒有然後了,這在整個開發界屢見不鮮。

在這樣的大背景下,加之我之前寫的 RxJava 2.0 系列 收到較好的反饋,誘導我想出這麼一個效能優化系列。

一些你可能需要知道的

瞭解我的知道,我出的系列基本都是比較基礎,而且側重於常見必備。所以不一定全面,也不一定深入,所以希望理解。

效能優化大概可以概括為:

  • 效能優化說起來很簡單,但做起來難。
  • 效能優化點多並且繁雜,需要耐心和經驗。也許每個優化點很小,但積累起來會從量變變成質的飛躍。
  • 效能優化必須建立在產品設計之上,不能為了追求效能而忽略了產品設計。

提供一些資源 ( 你可能需要梯子 )

善用 ArrayMap

程式記憶體的管理是否合理高效對應用的效能有著很大的影響,有時候對容器的使用不當也會導致記憶體管理效率低下。想必已經有很多童鞋知道了 SparseArray,但它只是用於替代 List。

我們經常會在程式中用到 HashMap,它非常好用,這毋庸置疑。但它卻非常耗記憶體。HashMap 的工作原理這裡我們就不講了,有興趣的自行科普。

更高效的 ArrayMap 容器

為了解決 HashMap 更佔記憶體的弊端,Android 提供了記憶體效率更高的 ArrayMap。它內部使用兩個陣列進行工作,其中一個陣列記錄 key hash 過後的順序列表,另外一個陣列按 key 的順序記錄 Key - Value 的值。如下圖所示:

當你想獲取某個 Value 的時候,ArrayMap 會計算輸入 key 轉換過後的 hash 值,然後對 hash 陣列使用二分查詢法尋找到對應的 index,然後我們可以通過這個 index 在另外一個陣列中直接訪問到需要的鍵值對。如果在第二個陣列鍵值對中的 key 和前面輸入的查詢 key 不一致,那麼就認為是發生了碰撞衝突。為了解決這個問題,我們會以該 key 為中心點,分別上下展開,逐個去對比查詢,直到找到匹配的值。如下圖所示:

隨著陣列中的物件越來越多,查詢訪問單個物件的花費也會跟著增長,這是在記憶體佔用與訪問時間之間做權衡交換。

既然ArrayMap中的記憶體佔用是連續不間斷的,那麼它是如何處理插入與刪除操作的呢?請看下圖所示,演示了Array的特性:


很明顯,ArrayMap 的插入與刪除的效率是不夠高的,但是如果陣列的列表只是在一百這個數量級上,則完全不用擔心這些插入與刪除的效率問題。HashMapArrayMap 之間的記憶體佔用效率對比圖如下:

HashMap 想必,ArrayMap 在迴圈遍歷的時候也更加簡單高效,因為其採用的是 fori 迴圈,而 HashMap 卻使用的是糟糕的 Iterator

並不是所有情況下都用 ArrayMap

ArrayMap 這麼優秀,但並不是所有情況下都適合使用 ArrayMap,我們應該在滿足下面兩個條件的時候才考慮使用 ArrayMap

  • 物件個數的數量級最好在 1000 以內。
  • 資料組織形式包含 Map 結構。

所以我們需要學會在特定清醒下選擇相對更加高效的實現方式。

UI 效能確實很重要

UI 介面是整個 APP 效能的最前端展示,也是最容易看出效能問題的地方。可以毫不誇張地說,UI 效能的好壞直接影響這使用者的體驗和留存。UI 效能的目標是:

  • 減少繪圖的等待時間。
  • 使幀率更加平穩、連貫。

UI 佈局的核心原則

核心原則一句話,儘可能地減少 View 的數量!

我們可以通過 includemergeviewstub 進行佈局複用,通過控制元件屬性 DrawableLeft、DrawableRight 等方式進行控制元件整合。

聽說我們要儘可能地用 RelativeLayout ?

想必一些資歷較老的 Android 開發者都知道,一開始系統預設建立的佈局是 LinearLayout,後面替換成了 RelativeLayout,現在又變成了 ConstraintLayout 。由於我對 ConstraintLayout 不是特別瞭解,所以這裡我著重說說 RelativeLayout 和 LinearLayout 。

我不知道在什麼時候聽說過,如果我們能用 RelativeLayout 的地方,儘量不要用 LinearLayout

這種說法是不對的,實際開發中,決不能簡單地說 RelativeLayout 和 LinearLayout 誰的效能更好,必須結合實際使用來進行分析。

基本可以總結為:一般情況下,如果使用 LinearLayout,則一定要保證層級不能太深;如果使用 RelativeLayout,則需要儘量避免巢狀。

後記

以上便是本期內容,由於樓主也是開發任務很多,所以只能在有空的時候更新。
如果想第一時間收到更新資訊的可以關注我的簡書:簡書地址
你也可以選擇關注我的公眾號:nanchen

相關文章