Java和Android架構
熱文導讀 | 點選標題閱讀
來自:斜槓Allen
連結:https://www.jianshu.com/p/9755da0f4e8f
說到 Android 系統手機,大部分人的印象是用了一段時間就變得有點卡頓,有些程式在執行期間莫名其妙的出現崩潰,開啟系統資料夾一看,發現多了很多檔案,然後用手機管家 APP 不斷地進行清理優化 ,才感覺執行速度稍微提高了點,就算手機在各種效能跑分軟體面前分數遙遙領先,還是感覺無論有多大的記憶體空間都遠遠不夠用。相信每個使用 Android 系統的使用者都有過以上類似經歷,確實,Android 系統在流暢性方面不如 IOS 系統,為何呢,明明在看手機硬體配置上時,Android 裝置都不會輸於 IOS 裝置,甚至都強於它,關鍵是在於軟體上。造成這種現象的原因是多方面的,簡單羅列幾點如下:
其實近年來,隨著 Android 版本不斷迭代,Google 提供的Android 系統已經越來越流暢,目前最新發布的版本是Android 8.0 Oreo。但是在國內大部分使用者用的 Android 手機系是各大廠商定製過的版本,往往不是最新的原生系統核心,可能絕大多數還停留在 Android 5.0 系統上,甚至 Android 6.0 以上所佔比例還偏小,更新存在延遲性。
由於 Android 系統原始碼是開放的,每個人只要遵從相應的協議,就可以對原始碼進行修改,那麼國內各個廠商就把基於 Android 原始碼改造成自己對外發布的系統,比如我們熟悉的小米手機 Miui 系統、華為手機 EMUI 系統、Oppo 手機 ColorOS 系統等。由於每個廠商都修改過 Android 原生系統原始碼,這裡面就會引發一個問題,那就是著名的Android 碎片化
由於存在著各種Android 碎片化和相容性問題,導致 Android 開發者在開發應用時需要對不同系統進行適配,同時每個 Android 開發者的開發水平參差不齊,寫出來的應用效能也都存在不同型別的問題,導致使用者在使用過程中使用者體驗感受不同,那麼有些問題使用者就會轉化為 Android 系統問題,進而影響對Android 手機的評價。
一、效能優化
今天想說的重點是Android APP效能優化,也就是在開發應用程式時應該注意的點有哪些,如何更好地提高使用者體驗。一個好的應用,除了要有吸引人的功能和互動之外,在效能上也應該有高的要求,即時應用非常具有特色,在產品前期可能吸引了部分使用者,但是使用者體驗不好的話,也會給產品帶來不好的口碑。那麼一個好的應用應該如何定義呢?主要有以下三方面:
業務/功能
符合邏輯的互動
優秀的效能
眾所周知,Android 系統作為以移動裝置為主的作業系統,硬體配置是有一定的限制的,雖然配置現在越來越高階,但仍然無法與 PC 相比,在 CPU 和記憶體上使用不合理或者耗費資源多時,就會碰到記憶體不足導致的穩定性問題、CPU 消耗太多導致的卡頓問題等。
面對問題時,大家想到的都是聯絡使用者,然後檢視日誌,但殊不知有關效能類問題的反饋,原因也非常難找,日誌大多用處不大,為何呢?因為效能問題大部分是非必現的問題,問題定位很難復現,而又沒有關鍵的日誌,當然就無法找到原因了。這些問題非常影響使用者體驗和功能使用,所以瞭解一些效能優化的一些解決方案就顯得很重要了,並在實際的專案中優化我們的應用,進而提高使用者體驗。
二、四個方面
可以把使用者體驗的效能問題主要總結為4個類別:
流暢
穩定
省電、省流量
安裝包小
效能問題的主要原因是什麼,原因有相同的,也有不同的,但歸根到底,不外乎記憶體使用、程式碼效率、合適的策略邏輯、程式碼質量、安裝包體積這一類問題,整理歸類如下:
效能優化圖
從圖中可以看到,打造一個高質量的應用應該以4個方向為目標:快、穩、省、小。
快:使用時避免出現卡頓,響應速度快,減少使用者等待的時間,滿足使用者期望。
穩:減低 crash 率和 ANR 率,不要在使用者使用過程中崩潰和無響應。
省:節省流量和耗電,減少使用者使用成本,避免使用時導致手機發燙。
小:安裝包小可以降低使用者的安裝成本。
要想達到這4個目標,具體實現是在右邊框裡的問題:卡頓、記憶體使用不合理、程式碼質量差、程式碼邏輯亂、安裝包過大,這些問題也是在開發過程中碰到最多的問題,在實現業務需求同時,也需要考慮到這點,多花時間去思考,如何避免功能完成後再來做優化,不然的話等功能實現後帶來的維護成本會增加。
三、卡頓優化
Android 應用啟動慢,使用時經常卡頓,是非常影響使用者體驗的,應該儘量避免出現。卡頓的場景有很多,按場景可以分為4類:UI 繪製、應用啟動、頁面跳轉、事件響應,如圖:
卡頓場景
這4種卡頓場景的根本原因可以分為兩大類:
介面繪製。主要原因是繪製的層級深、頁面複雜、重新整理不合理,由於這些原因導致卡頓的場景更多出現在 UI 和啟動後的初始介面以及跳轉到頁面的繪製上。
資料處理。導致這種卡頓場景的原因是資料處理量太大,一般分為三種情況,一是資料在處理 UI 執行緒,二是資料處理佔用 CPU 高,導致主執行緒拿不到時間片,三是記憶體增加導致 GC 頻繁,從而引起卡頓。
引起卡頓的原因很多,但不管怎麼樣的原因和場景,最終都是通過裝置螢幕上顯示來達到使用者,歸根到底就是顯示有問題,所以,要解決卡頓,就要先了解 Android 系統的顯示原理。
Android系統顯示原理
Android 顯示過程可以簡單概括為:Android 應用程式把經過測量、佈局、繪製後的 surface 快取資料,通過 SurfaceFlinger 把資料渲染到顯示螢幕上, 通過 Android 的重新整理機制來重新整理資料。也就是說應用層負責繪製,系統層負責渲染,通過程序間通訊把應用層需要繪製的資料傳遞到系統層服務,系統層服務通過重新整理機制把資料更新到螢幕上。
我們都知道在 Android 的每個 View 繪製中有三個核心步驟:Measure、Layout、Draw。具體實現是從 ViewRootImp 類的performTraversals() 方法開始執行,Measure 和 Layout都是通過遞迴來獲取 View 的大小和位置,並且以深度作為優先順序,可以看出層級越深、元素越多、耗時也就越長。
真正把需要顯示的資料渲染到螢幕上,是通過系統級程序中的 SurfaceFlinger 服務來實現的,那麼這個SurfaceFlinger 服務主要做了哪些工作呢?如下:
響應客戶端事件,建立 Layer 與客戶端的 Surface 建立連線。
接收客戶端資料及屬性,修改 Layer 屬性,如尺寸、顏色、透明度等。
將建立的 Layer 內容重新整理到螢幕上。
維持 Layer 的序列,並對 Layer 最終輸出做出裁剪計算。
既然是兩個不同的程序,那麼肯定是需要一個跨程序的通訊機制來實現資料傳遞,在 Android 顯示系統中,使用了 Android 的匿名共享記憶體:SharedClient,每一個應用和 SurfaceFlinger 之間都會建立一個SharedClient ,然後在每個 SharedClient 中,最多可以建立 31 個 SharedBufferStack,每個 Surface 都對應一個 SharedBufferStack,也就是一個 Window。
一個 SharedClient 對應一個Android 應用程式,而一個 Android 應用程式可能包含多個視窗,即 Surface 。也就是說 SharedClient 包含的是 SharedBufferStack的集合,其中在顯示重新整理機制中用到了雙緩衝和三重緩衝技術。最後總結起來顯示整體流程分為三個模組:應用層繪製到快取區,SurfaceFlinger 把快取區資料渲染到螢幕,由於是不同的程序,所以使用 Android 的匿名共享記憶體 SharedClient 快取需要顯示的資料來達到目的。
除此之外,我們還需要一個名詞:FPS。FPS 表示每秒傳遞的幀數。在理想情況下,60 FPS 就感覺不到卡,這意味著每個繪製時長應該在16 ms 以內。但是 Android 系統很有可能無法及時完成那些複雜的頁面渲染操作。Android 系統每隔 16ms 發出 VSYNC 訊號,觸發對 UI 進行渲染,如果每次渲染都成功,這樣就能夠達到流暢的畫面所需的 60FPS。如果某個操作花費的時間是 24ms ,系統在得到 VSYNC 訊號時就無法正常進行正常渲染,這樣就發生了丟幀現象。那麼使用者在 32ms 內看到的會是同一幀畫面,這種現象在執行動畫或滑動列表比較常見,還有可能是你的 Layout 太過複雜,層疊太多的繪製單元,無法在 16ms 完成渲染,最終引起重新整理不及時。
卡頓根本原因
根據Android 系統顯示原理可以看到,影響繪製的根本原因有以下兩個方面:
繪製任務太重,繪製一幀內容耗時太長。
主執行緒太忙,根據系統傳遞過來的 VSYNC 訊號來時還沒準備好資料導致丟幀。
繪製耗時太長,有一些工具可以幫助我們定位問題。主執行緒太忙則需要注意了,主執行緒關鍵職責是處理使用者互動,在螢幕上繪製畫素,並進行載入顯示相關的資料,所以特別需要避免任何主執行緒的事情,這樣應用程式才能保持對使用者操作的即時響應。總結起來,主執行緒主要做以下幾個方面工作:
UI 生命週期控制
系統事件處理
訊息處理
介面佈局
介面繪製
介面重新整理
除此之外,應該儘量避免將其他處理放在主執行緒中,特別複雜的資料計算和網路請求等。
效能分析工具
效能問題並不容易復現,也不好定位,但是真的碰到問題還是需要去解決的,那麼分析問題和確認問題是否解決,就需要藉助相應的的除錯工具,比如檢視 Layout 層次的 Hierarchy View、Android 系統上帶的 GPU Profile 工具和靜態程式碼檢查工具 Lint 等,這些工具對效能優化起到非常重要的作用,所以要熟悉,知道在什麼場景用什麼工具來分析。
1,Profile GPU Rendering
在手機開發者模式下,有一個卡頓檢測工具叫做:Profile GPU Rendering,如圖:
Profile GPU Rendering
它的功能特點如下:
一個圖形監測工具,能實時反應當前繪製的耗時
橫軸表示時間,縱軸表示每一幀的耗時
隨著時間推移,從左到右的重新整理呈現
提供一個標準的耗時,如果高於標準耗時,就表示當前這一幀丟失
2,TraceView
TraceView 是 Android SDK 自帶的工具,用來分析函式呼叫過程,可以對 Android 的應用程式以及 Framework 層的程式碼進行效能分析。它是一個圖形化的工具,最終會產生一個圖表,用於對效能分析進行說明,可以分析到每一個方法的執行時間,其中可以統計出該方法呼叫次數和遞迴次數,實際時長等引數維度,使用非常直觀,分析效能非常方便。
3,Systrace UI 效能分析
Systrace 是 Android 4.1及以上版本提供的效能資料取樣和分析工具,它是通過系統的角度來返回一些資訊。它可以幫助開發者收集 Android 關鍵子系統,如 surfaceflinger、WindowManagerService 等 Framework 部分關鍵模組、服務、View系統等執行資訊,從而幫助開發者更直觀地分析系統瓶頸,改進效能。Systrace 的功能包括跟蹤系統的 I/O 操作、核心工作佇列、CPU 負載等,在 UI 顯示效能分析上提供很好的資料,特別是在動畫播放不流暢、渲染卡等問題上。
優化建議
1,佈局優化
佈局是否合理主要影響的是頁面測量時間的多少,我們知道一個頁面的顯示測量和繪製過程都是通過遞迴來完成的,多叉樹遍歷的時間與樹的高度h有關,其時間複雜度 O(h),如果層級太深,每增加一層則會增加更多的頁面顯示時間,所以佈局的合理性就顯得很重要。
那佈局優化有哪些方法呢,主要通過減少層級、減少測量和繪製時間、提高複用性三個方面入手。總結如下:
減少層級。合理使用 RelativeLayout 和 LinerLayout,合理使用Merge。
提高顯示速度。使用 ViewStub,它是一個看不見的、不佔佈局位置、佔用資源非常小的檢視物件。
佈局複用。可以通過標籤來提高複用。
儘可能少用wrap_content。wrap_content 會增加布局 measure 時計算成本,在已知寬高為固定值時,不用wrap_content 。
刪除控制元件中無用的屬性。
2,避免過度繪製
過度繪製是指在螢幕上的某個畫素在同一幀的時間內被繪製了多次。在多層次重疊的 UI 結構中,如果不可見的 UI 也在做繪製的操作,就會導致某些畫素區域被繪製了多次,從而浪費了多餘的 CPU 以及 GPU 資源。
如何避免過度繪製呢,如下:
佈局上的優化。移除 XML 中非必須的背景,移除 Window 預設的背景、按需顯示佔位背景圖片
自定義View優化。使用 canvas.clipRect()來幫助系統識別那些可見的區域,只有在這個區域內才會被繪製。
3,啟動優化
通過對啟動速度的監控,發現影響啟動速度的問題所在,優化啟動邏輯,提高應用的啟動速度。啟動主要完成三件事:UI 佈局、繪製和資料準備。因此啟動速度優化就是需要優化這三個過程:
UI 佈局。應用一般都有閃屏頁,優化閃屏頁的 UI 佈局,可以通過 Profile GPU Rendering 檢測丟幀情況。
啟動載入邏輯優化。可以採用分佈載入、非同步載入、延期載入策略來提高應用啟動速度。
資料準備。資料初始化分析,載入資料可以考慮用執行緒初始化等策略。
4,合理的重新整理機制
在應用開發過程中,因為資料的變化,需要重新整理頁面來展示新的資料,但頻繁重新整理會增加資源開銷,並且可能導致卡頓發生,因此,需要一個合理的重新整理機制來提高整體的 UI 流暢度。合理的重新整理需要注意以下幾點:
儘量減少重新整理次數。
儘量避免後臺有高的 CPU 執行緒執行。
縮小重新整理區域。
5,其他
在實現動畫效果時,需要根據不同場景選擇合適的動畫框架來實現。有些情況下,可以用硬體加速方式來提供流暢度。
四、記憶體優化
在 Android 系統中有個垃圾記憶體回收機制,在虛擬機器層自動分配和釋放記憶體,因此不需要在程式碼中分配和釋放某一塊記憶體,從應用層面上不容易出現記憶體洩漏和記憶體溢位等問題,但是需要記憶體管理。Android 系統在記憶體管理上有一個 Generational Heap Memory 模型,記憶體回收的大部分壓力不需要應用層關心, Generational Heap Memory 有自己一套管理機制,當記憶體達到一個閾值時,系統會根據不同的規則自動釋放系統認為可以釋放的記憶體,也正是因為 Android 程式把記憶體控制的權力交給了 Generational Heap Memory,一旦出現記憶體洩漏和溢位方面的問題,排查錯誤將會成為一項異常艱難的工作。除此之外,部分 Android 應用開發人員在開發過程中並沒有特別關注記憶體的合理使用,也沒有在記憶體方面做太多的優化,當應用程式同時執行越來越多的任務,加上越來越複雜的業務需求時,完全依賴 Android 的記憶體管理機制就會導致一系列效能問題逐漸呈現,對應用的穩定性和效能帶來不可忽視的影響,因此,解決記憶體問題和合理優化記憶體是非常有必要的。
Android記憶體管理機制
Android 應用都是在 Android 的虛擬機器上執行,應用 程式的記憶體分配與垃圾回收都是由虛擬機器完成的。在 Android 系統,虛擬機器有兩種執行模式:Dalvik 和 ART。
1,Java物件生命週期
Java物件生命週期
一般Java物件在虛擬機器上有7個執行階段:
建立階段->應用階段->不可見階段->不可達階段->收集階段->終結階段->物件空間重新分配階段
2,記憶體分配
在 Android 系統中,記憶體分配實際上是對堆的分配和釋放。當一個 Android 程式啟動,應用程序都是從一個叫做 Zygote 的程序衍生出來,系統啟動 Zygote 程序後,為了啟動一個新的應用程式程序,系統會衍生 Zygote 程序生成一個新的程序,然後在新的程序中載入並執行應用程式的程式碼。其中,大多數的 RAM pages 被用來分配給Framework 程式碼,同時促使 RAM 資源能夠在應用所有程序之間共享。
但是為了整個系統的記憶體控制需要,Android 系統會為每一個應用程式都設定一個硬性的 Dalvik Heap Size 最大限制閾值,整個閾值在不同裝置上會因為 RAM 大小不同而有所差異。如果應用佔用記憶體空間已經接近整個閾值時,再嘗試分配記憶體的話,就很容易引起記憶體溢位的錯誤。
3,記憶體回收機制
我們需要知道的是,在 Java 中記憶體被分為三個區域:Young Generation(年輕代)、Old Generation(年老代)、Permanent Generation(持久代)。最近分配的物件會存放在 Young Generation 區域。物件在某個時機觸發 GC 回收垃圾,而沒有回收的就根據不同規則,有可能被移動到 Old Generation,最後累積一定時間在移動到 Permanent Generation 區域。系統會根據記憶體中不同的記憶體資料型別分別執行不同的 GC 操作。GC 通過確定物件是否被活動物件引用來確定是否收集物件,進而動態回收無任何引用的物件佔據的記憶體空間。但需要注意的是頻繁的 GC 會增加應用的卡頓情況,影響應用的流暢性,因此需要儘量減少系統 GC 行為,以便提高應用的流暢度,減小卡頓發生的概率。
記憶體分析工具
做記憶體優化前,需要了解當前應用的記憶體使用現狀,通過現狀去分析哪些資料型別有問題,各種型別的分佈情況如何,以及在發現問題後如何發現是哪些具體物件導致的,這就需要相關工具來幫助我們。
1,Memory Monitor
Memory Monitor 是一款使用非常簡單的圖形化工具,可以很好地監控系統或應用的記憶體使用情況,主要有以下功能:
顯示可用和已用記憶體,並且以時間為維度實時反應記憶體分配和回收情況。
快速判斷應用程式的執行緩慢是否由於過度的記憶體回收導致。
快速判斷應用是否由於記憶體不足導致程式崩潰。
2,Heap Viewer
Heap Viewer 的主要功能是檢視不同資料型別在記憶體中的使用情況,可以看到當前程序中的 Heap Size 的情況,分別有哪些型別的資料,以及各種型別資料佔比情況。通過分析這些資料來找到大的記憶體物件,再進一步分析這些大物件,進而通過優化減少記憶體開銷,也可以通過資料的變化發現記憶體洩漏。
3,Allocation Tracker
Memory Monitor 和 Heap Viewer 都可以很直觀且實時地監控記憶體使用情況,還能發現記憶體問題,但發現記憶體問題後不能再進一步找到原因,或者發現一塊異常記憶體,但不能區別是否正常,同時在發現問題後,也不能定位到具體的類和方法。這時就需要使用另一個記憶體分析工具 Allocation Tracker,進行更詳細的分析, Allocation Tracker 可以分配跟蹤記錄應用程式的記憶體分配,並列出了它們的呼叫堆疊,可以檢視所有物件記憶體分配的週期。
4,Memory Analyzer Tool(MAT)
MAT 是一個快速,功能豐富的 Java Heap 分析工具,通過分析 Java 程序的記憶體快照 HPROF 分析,從眾多的物件中分析,快速計算出在記憶體中物件佔用的大小,檢視哪些物件不能被垃圾收集器回收,並可以通過檢視直觀地檢視可能造成這種結果的物件。
常見記憶體洩漏場景
如果在記憶體洩漏發生後再去找原因並修復會增加開發的成本,最好在編寫程式碼時就能夠很好地考慮記憶體問題,寫出更高質量的程式碼,這裡列出一些常見的記憶體洩漏場景,在以後的開發過程中需要避免這類問題。
資源性物件未關閉。比如Cursor、File檔案等,往往都用了一些緩衝,在不使用時,應該及時關閉它們。
註冊物件未登出。比如事件註冊後未登出,會導致觀察者列表中維持著物件的引用。
類的靜態變數持有大資料物件。
非靜態內部類的靜態例項。
Handler臨時性記憶體洩漏。如果Handler是非靜態的,容易導致 Activity 或 Service 不會被回收。
容器中的物件沒清理造成的記憶體洩漏。
WebView。WebView 存在著記憶體洩漏的問題,在應用中只要使用一次 WebView,記憶體就不會被釋放掉。
除此之外,記憶體洩漏可監控,常見的就是用LeakCanary 第三方庫,這是一個檢測記憶體洩漏的開源庫,使用非常簡單,可以在發生記憶體洩漏時告警,並且生成 leak tarce 分析洩漏位置,同時可以提供 Dump 檔案進行分析。
優化記憶體空間
沒有記憶體洩漏,並不意味著記憶體就不需要優化,在移動裝置上,由於物理裝置的儲存空間有限,Android 系統對每個應用程序也都分配了有限的堆記憶體,因此使用最小記憶體物件或者資源可以減小記憶體開銷,同時讓GC 能更高效地回收不再需要使用的物件,讓應用堆記憶體保持充足的可用記憶體,使應用更穩定高效地執行。常見做法如下:
物件引用。強引用、軟引用、弱引用、虛引用四種引用型別,根據業務需求合理使用不同,選擇不同的引用型別。
減少不必要的記憶體開銷。注意自動裝箱,增加記憶體複用,比如有效利用系統自帶的資源、檢視複用、物件池、Bitmap物件的複用。
使用最優的資料型別。比如針對資料類容器結構,可以使用ArrayMap資料結構,避免使用列舉型別,使用快取Lrucache等等。
圖片記憶體優化。可以設定點陣圖規格,根據取樣因子做壓縮,用一些圖片快取方式對圖片進行管理等等。
五、穩定性優化
Android 應用的穩定性定義很寬泛,影響穩定性的原因很多,比如記憶體使用不合理、程式碼異常場景考慮不周全、程式碼邏輯不合理等,都會對應用的穩定性造成影響。其中最常見的兩個場景是:Crash 和 ANR,這兩個錯誤將會使得程式無法使用,比較常用的解決方式如下:
提高程式碼質量。比如開發期間的程式碼稽核,看些程式碼設計邏輯,業務合理性等。
程式碼靜態掃描工具。常見工具有Android Lint、Findbugs、Checkstyle、PMD等等。
Crash監控。把一些崩潰的資訊,異常資訊及時地記錄下來,以便後續分析解決。
Crash上傳機制。在Crash後,儘量先儲存日誌到本地,然後等下一次網路正常時再上傳日誌資訊。
六、耗電優化
在移動裝置中,電池的重要性不言而喻,沒有電什麼都幹不成。對於作業系統和裝置開發商來說,耗電優化一致沒有停止,去追求更長的待機時間,而對於一款應用來說,並不是可以忽略電量使用問題,特別是那些被歸為“電池殺手”的應用,最終的結果是被解除安裝。因此,應用開發者在實現需求的同時,需要儘量減少電量的消耗。
在 Android5.0 以前,在應用中測試電量消耗比較麻煩,也不準確,5.0 之後專門引入了一個獲取裝置上電量消耗資訊的 API:Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系統電量分析工具,和Systrace 一樣,是一款圖形化資料分析工具,直觀地展示出手機的電量消耗過程,通過輸入電量分析檔案,顯示消耗情況,最後提供一些可供參考電量優化的方法。
除此之外,還有一些常用方案可提供:
計算優化,避開浮點運算等。
避免 WaleLock 使用不當。
使用 Job Scheduler。
七、安裝包大小優化
應用安裝包大小對應用使用沒有影響,但應用的安裝包越大,使用者下載的門檻越高,特別是在行動網路情況下,使用者在下載應用時,對安裝包大小的要求更高,因此,減小安裝包大小可以讓更多使用者願意下載和體驗產品。
常用應用安裝包的構成,如圖所示:
應用安裝包構成
從圖中我們可以看到:
assets資料夾。存放一些配置檔案、資原始檔,assets不會自動生成對應的 ID,而是通過 AssetManager 類的介面獲取。
res。res 是 resource 的縮寫,這個目錄存放資原始檔,會自動生成對應的 ID 並對映到 .R 檔案中,訪問直接使用資源 ID。
META-INF。儲存應用的簽名信息,簽名信息可以驗證 APK 檔案的完整性。
AndroidManifest.xml。這個檔案用來描述 Android 應用的配置資訊,一些元件的註冊資訊、可使用許可權等。
classes.dex。Dalvik 位元組碼程式,讓 Dalvik 虛擬機器可執行,一般情況下,Android 應用在打包時通過 Android SDK 中的 dx 工具將 Java 位元組碼轉換為 Dalvik 位元組碼。
resources.arsc。記錄著資原始檔和資源 ID 之間的對映關係,用來根據資源 ID 尋找資源。
減少安裝包大小的常用方案
程式碼混淆。使用proGuard 程式碼混淆器工具,它包括壓縮、優化、混淆等功能。
資源優化。比如使用 Android Lint 刪除冗餘資源,資原始檔最少化等。
圖片優化。比如利用 AAPT 工具對 PNG 格式的圖片做壓縮處理,降低圖片色彩位數等。
避免重複功能的庫,使用 WebP圖片格式等。
外掛化。比如功能模組放在伺服器上,按需下載,可以減少安裝包大小。
八、小結
效能優化不是更新一兩個版本就可以解決的,是持續性的需求,持續整合迭代反饋。在實際的專案中,在專案剛開始的時候,由於人力和專案完成時間限制,效能優化的優先順序比較低,等進入專案投入使用階段,就需要把優先順序提高,但在專案初期,在設計架構方案時,效能優化的點也需要提早考慮進去,這就體現出一個程式設計師的技術功底了。
什麼時候開始有效能優化的需求,往往都是從發現問題開始,然後分析問題原因及背景,進而尋找最優解決方案,最終解決問題,這也是日常工作中常會用到的處理方式。
最後,歡迎大家加入我們的知識星球,第二期開期起航火熱進行中,已有近1000人加入學習:
歡迎大家儘早加入,這期是到2019年3月10日結束,所以越早加入越好,優惠活動結束,現入圈費用由79元提至89元,以後每滿100人費用增加10元~
微信掃描或者點選上方二維碼領取Android\Python\AI\Java等高階進階資源
更多學習資料點選下面的“閱讀原文”獲取