Android 性能優化之內存優化

文章目錄

  • Android 性能優化之內存優化
    • 內存問題
      • 內存抖動
      • 內存泄露
      • 內存溢出
    • 檢測工具
      • Memory Profiler
      • Memory Analyzer
      • LeakCanary
    • 內存管理機制
      • Java
      • Android
    • 解決
      • 內存抖動問題
        • 模擬問題代碼
        • 使用Memory Profiler工具檢測
        • 優化技巧
      • 內存泄露問題
        • 模擬問題代碼
        • 使用LeakCanary工具檢測
        • 優化技巧
      • Bitmap優化
        • Bitmap內存模型
        • 資源文件目錄
        • 優化技巧
    • 源碼下載

Android 性能優化之內存優化

內存問題

  • 內存抖動
  • 內存泄露
  • 內存溢出

內存抖動

內存抖動指的是在短時間內大量對象被創建和銷毀,導致頻繁的垃圾回收(Garbage Collection, GC)活動。這種頻繁的GC活動會占用大量的CPU資源,可能導致應用程序的卡頓或性能下降。

表現:內存曲線呈鋸齒狀。

內存泄露

內存泄露是指應用程序持有了不再需要的對象的引用,導致這些對象無法被垃圾回收器回收,從而占用了本可以被釋放的內存空間。隨著時間的推移,內存泄露會導致可用內存越來越少,最終可能導致應用程序崩潰或性能下降。

內存溢出

內存溢出是指應用程序嘗試分配更多的內存空間,但系統無法滿足這個請求,因為已經沒有足夠的內存空間可供分配。這通常會導致應用程序拋出OutOfMemoryError異常。

檢測工具

  • Memory Profiler
  • Memory Analyzer
  • LeakCanary

Memory Profiler

  • Memory Profiler 是 Android Studio自帶的內存分析工具。
  • 實時圖表展示程序內存使用情況。
  • 識別內存泄露、抖動等。
  • 提供捕獲堆轉儲、強制GC以及跟蹤內存分配的能力。

Memory Analyzer

  • 強大的 Java Heap 分析工具,查找內存泄露已經內存占用。
  • 生成整體報告、分析問題等。

LeakCanary

  • 自動內存泄露檢測。
    • LeakCanary自動檢測這些對象的泄露問題:Activity、Fragment、View、ViewModel、Service。
  • 官網:https://github.com/square/leakcanary

內存管理機制

Java

Java 內存結構:堆、虛擬機棧、方法區、程序計數器、本地方法棧。

Java 內存回收算法:

  • 標記-清除算法:
    1. 標記出所需要回收的對象
    2. 統一回收所有標記的對象。
  • 復制算法:
    1. 將內存劃分為大小相等的兩塊。
    2. 一款內存用完后復制存活對象到另一塊中。
  • 標記-整理算法:
    1. 標記過程與“標記-清除“算法一樣。
    2. 存活對象往一端進行移動。
    3. 清除其余內存。
  • 分代收集算法:
    • 結合多種收集算法優勢。
    • 新生代對象存活率低,使用復制算法。
    • 老年代對象存活率高,使用標記-整理算法。

標記-清除算法缺點:標記和清除效率不高,會產生大量不連續的內存碎片。

復制算法:實現簡單,運行高效。缺點:浪費一半空間。

標記-整理算法:避免標記-清理導致的內存碎片,避免復制算法的空間浪費。

Android

Android內存彈性分配,分配值與最大值受具體設備影響。

Dalvik 回收算法和 ART 回收算法都是 Android 操作系統中用于內存管理的垃圾回收機制

Dalvik 回收算法:

  • 標記-清除算法。
  • 優點是實現簡單。缺點是在標記和清除階段都會暫停應用程序的執行,這會導致應用程序出現短暫的卡頓,影響用戶體驗。

Art 回收算法:

  • 壓縮式垃圾回收(Compacting Garbage Collection)的算法。在標記-清除算法的基礎上進行了改進,以減少垃圾回收過程中的暫停時間。
  • 并發標記:ART 引入了并發標記階段,這意味著它可以與應用程序的執行同時進行。這減少了由于垃圾回收導致的暫停時間。
  • 清除和壓縮:在清除階段,ART 不僅清除未被標記的對象,還會壓縮內存,這意味著它會將存活的對象移動到一起,減少內存碎片。這使得內存管理更高效,并減少了內存分配失敗的可能性。
  • 自適應回收:ART 還引入了自適應回收的概念,這意味著它會根據應用程序的行為和內存使用模式自動調整垃圾回收的頻率和方式。這使得 ART 可以更好地適應不同的應用程序需求。

LMK機制:

  • Low Memory Killer 機制。
  • 主要作用是在系統內存不足時,根據一定的優先級策略,結束一些后臺進程,以釋放內存,保證系統的穩定性和響應性。

解決

內存抖動問題

模擬問題代碼
public class ShakeActivity extends AppCompatActivity {private static Handler mHandler = new Handler() {@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);String str = "";for (int i = 0; i < 10000000; i++) {str += i;}mHandler.sendEmptyMessageDelayed(1, 30);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_shake);}public void startClick(View view) {mHandler.sendEmptyMessage(1);}@Overrideprotected void onDestroy() {super.onDestroy();mHandler.removeCallbacksAndMessages(null);}
}
使用Memory Profiler工具檢測

Memory Profiler 可以查看內存分配情況,點擊“Record Java/Kotlin allocations"。

在這里插入圖片描述

上面的含義:

  • Java:Java 或 Kotlin 代碼分配的內存。
  • Native:C 或 C++ 代碼分配的內存。
  • Graphics:圖形緩沖區隊列為向屏幕顯示像素(包括 GL 表面、GL 紋理等等)所使用的內存。CPU共享的內存。
  • Stack:應用中的原生堆棧和 Java 堆棧使用的內存。這通常與您的應用運行多少線程有關。
  • 應用用于處理代碼和資源(如 dex 字節碼、經過優化或編譯的 dex 代碼、.so 庫和字體)的內存。
  • 應用使用的系統不確定如何分類的內存。
  • 應用分配的 Java/Kotlin 對象數。此數字沒有計入 C 或 C++ 中分配的對象。

下面的含義:

  • Allocations:通過 malloc()new 運算符分配的對象數量。
  • Deallocations:通過 free()delete 運算符解除分配的對象數量。
  • Allocations Size:選定時間段內所有分配的總大小,單位是字節。
  • Deallocations Size:選定時間段內釋放內存的總大小,單位是字節。
  • Total Count:Allocations 減去 Deallocations 的結果。
  • Remaining Size:Allocations Size 減去 Deallocations Size 的結果。
  • Shallow Size:堆中所有實例的總大小,單位是字節。

上圖分析:

在這里插入圖片描述

這塊地方 Allocations 和 Deallocations 的數值比較相近,同時 Shallow Size 比較大,說明可能頻繁的創建和銷毀對象。

在這里插入圖片描述

點擊后,可以查看調用棧信息,結合代碼可以推測出 Handler 地方存在內存抖動問題。

優化技巧
  • 避免大量頻繁創建和銷毀對象。

內存泄露問題

模擬問題代碼
public class CallbackManager {public static ArrayList<Callback> sCallbacks = new ArrayList<>();public static void addCallback(Callback callback) {sCallbacks.add(callback);}public static void removeCallback(Callback callback) {sCallbacks.remove(callback);}
}
public class LeakActivity extends AppCompatActivity implements Callback {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_leak);ImageView imageView = findViewById(R.id.imageView);Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.splash);imageView.setImageBitmap(bitmap);CallbackManager.addCallback(this);}@Overridepublic void onOperate() {}
}
使用LeakCanary工具檢測

添加依賴庫:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'

發生內存泄露后,LeakCanary會生成相關信息,并自動轉儲:

在這里插入圖片描述

上圖可知:是 LeakActivity 發生內存泄露了,并顯示出引用鏈關系。

當然也可以生成 hprof 文件,通過 Profiler 工具查看具體信息:

在這里插入圖片描述

上圖可知:發生了10個泄露點,其中就有 LeakActivity,點擊 LeakActivity 可以查看這內存泄露的對象,并查看引用鏈,可知是被ArrayList持有了。

優化技巧
  • 及時回收集合元素。
  • 避免static引用過多實例。
  • 使用靜態內部類。
  • 及時關閉資源對象。

Bitmap優化

使用完Bitmap后若不釋放圖片資源,容易造成內存泄露,從而導致內存溢出

Bitmap內存模型
  • api10之前(Android2.3.3):Bitmap對象放在堆內存,像素數據放在本地內存。
  • api10之后:均在堆內存。
  • api26之后(Android8.0):像素數據放在本地內存。使得native層的Bitmap像素數據可以和Java層的對象一起快速釋放。

內存回收:

  • 在Android 3.0之前,需要手動調用Bitmap.recycle()進行Bitmap的回收。
  • 從Android 3.0開始,系統提供了更智能的內存管理,大多數情況下不需要手動回收Bitmap。

Bitmap的像素配置:

Config占用字節大小(byte)說明
ALPHA_81單透明通道
RGB_5652簡易RGB色調
ARGB_8888424位真彩色
RGBA_F168Android 8.0 新增(HDR)

計算Btimap占用內存:

  • Bitmap#getByteCount()
  • getWidth() * getHeight() * 1像素占用內存
資源文件目錄

資源文件問題:

  • mdpi (中等密度):大約160dpi,1x資源。
  • hdpi (高密度):大約240dpi,1.5x資源。
  • xhdpi (超高密度):大約320dpi,2x資源。
  • xxhdpi (超超高密度):大約480dpi,3x資源。
  • xxxhdpi (超超超高密度):大約640dpi,4x資源。

測試代碼:

private void printBitmap(Bitmap bitmap, String drawable) {String builder = drawable +" Bitmap占用內存:" +bitmap.getByteCount() +" width:" +bitmap.getWidth() +" height:" +bitmap.getHeight() +" 1像素占用大小:" +getByteBy1px(bitmap.getConfig());Log.e("TAG", builder);
}private int getByteBy1px(Bitmap.Config config) {if (Bitmap.Config.ALPHA_8.equals(config)) {return 1;} else if (Bitmap.Config.RGB_565.equals(config)) {return 2;} else if (Bitmap.Config.ARGB_8888.equals(config)) {return 4;}return 1;
}
// 邏輯密度
float density = metrics.density;
// 物理密度
int densityDpi = metrics.densityDpi;
Log.e("TAG", density + "-" + densityDpi);// 1倍圖
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.splash1);
printBitmap(bitmap1, "drawable-mdpi");// 2倍圖
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.splash2);
printBitmap(bitmap2, "drawable-xhdpi");// 3倍圖
Bitmap bitmap3 = BitmapFactory.decodeResource(getResources(), R.drawable.splash3);
printBitmap(bitmap3, "drawable-xxhdpi");// 4倍圖
Bitmap bitmap4 = BitmapFactory.decodeResource(getResources(), R.drawable.splash4);
printBitmap(bitmap4, "drawable-xxxhdpi");// drawable
Bitmap bitmap5 = BitmapFactory.decodeResource(getResources(), R.drawable.splash);
printBitmap(bitmap5, "drawable");
/*3.0-480drawable-mdpi Bitmap占用內存:37127376 width:2574 height:3606 1像素占用大小:4drawable-xhdpi Bitmap占用內存:9281844 width:1287 height:1803 1像素占用大小:4drawable-xxhdpi Bitmap占用內存:4125264 width:858 height:1202 1像素占用大小:4drawable-xxxhdpi Bitmap占用內存:2323552 width:644 height:902 1像素占用大小:4drawable Bitmap占用內存:37127376 width:2574 height:3606 1像素占用大小:4*/

說明:

在 mdpi 的設備上 1dp1px,在 xhdpi 的設備上 1dp2px,在 xxhdpi 的設備上 1dp==3px。

因此當前設備是 xxhdpi,因此同一張圖片在 xxhdpi 資源下寬是858,在 mdpi 資源下會放大3倍寬是2574,在 xhdpi 資源下會放大1.5倍寬是1287。

優化技巧
  • 設置多套圖片資源。
  • 選擇合適的解碼方式。
  • 設置圖片緩存。

源碼下載

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/diannao/44618.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/44618.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/44618.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

順序結構 ( 四 ) —— 標準數據類型 【互三互三】

序 C語言提供了豐富的數據類型&#xff0c;本節介紹幾種基本的數據類型&#xff1a;整型、實型、字符型。它們都是系統定義的簡單數據類型&#xff0c;稱為標準數據類型。 整型&#xff08;integer&#xff09; 在C語言中&#xff0c;整型類型標識符為int。根據整型變量的取值范…

開源大勢所趨

一、開源項目的發展趨勢 技術棧多樣化與專業化&#xff1a;隨著技術的不斷進步&#xff0c;開源項目涵蓋了從云計算、大數據、人工智能到區塊鏈、物聯網等各個領域&#xff0c;技術棧日益豐富和專業化。這種趨勢使得開發者能夠根據自己的需求選擇最適合的技術工具&#xff0c;促…

dify-api的Dockerfile分析

一.dify-api的Dockerfile文件 dify-api的Dockerfile文件如下所示&#xff1a; # base image FROM python:3.10-slim-bookworm AS baseLABEL maintainer"takatostgmail.com"# install packages FROM base as packagesRUN apt-get update \&& apt-get install…

nginx安裝配置視頻頻服務器-windows

編譯安裝nginx 1、安裝perl 安裝地址: https://strawberryperl.com&#xff0c;選擇msi安裝程序即可 2、安裝sed for windows 下載地址&#xff1a;https://sourceforge.net/projects/gnuwin32/files/sed/&#xff0c;執行安裝程序結束后&#xff0c;將安裝包bin目錄配置到…

【seo常見的問題】搜索引擎

1、讓網站訪問量提高的最好的方法是什么? 了解搜索引擎行為和搜索用戶的行為&#xff0c;就是通過觀察搜索引擎排名機制獲得有效途徑&#xff0c;提供效率&#xff0c;并且通過一些相關數據&#xff0c;了解到用戶的搜索行為。 2、我要你把一個站的關鍵詞排名排到首頁&#x…

【Adobe】動作捕獲和動畫制作軟件Character Animator

Adobe Character Animator 是一款由Adobe公司出品的動作捕獲和動畫制作軟件&#xff0c;旨在幫助用戶直觀地制作2D&#xff08;二維&#xff09;人物動畫、實時動畫&#xff0c;并發布動畫。這款軟件功能強大、操作簡單&#xff0c;非常適合動畫制作者、直播主以及社交媒體內容…

【STM32 ARM】操作寄存器控制led

文章目錄 前言GPIO操作方法led原理圖設置時鐘APB的概念 設置APB設置輸出引腳設置引腳高低電平寄存器尋找寄存器地址 總結 前言 STM32是STMicroelectronics&#xff08;意法半導體&#xff09;公司的一款32位Flash微控制器產品&#xff0c;基于ARM Cortex?-M內核。STM32系列微…

Groovy vs Kotlin 在Gradle配置文件中的差異與選擇

人不走空 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌賦&#xff1a;斯是陋室&#xff0c;惟吾德馨 目錄 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌…

beyond Compare連接 openWrt 和 VsCode

連接步驟總結 1. 新建會話 -> 文件夾比較 2.點擊瀏覽文件夾 3.在彈出頁面 配置 ftp 3.1&#xff09;選中ftp 配置文件 3.2)選中ssh2 3.3)填寫我們需要遠端連接的主機信息 先點擊連接并瀏覽 得到下方文件夾 彈出無效登錄&#xff0c;說明需要密碼 我們返回右鍵剛剛創建的新 …

C++ | Leetcode C++題解之第227題基本計算器II

題目&#xff1a; 題解&#xff1a; class Solution { public:int calculate(string s) {vector<int> stk;char preSign ;int num 0;int n s.length();for (int i 0; i < n; i) {if (isdigit(s[i])) {num num * 10 int(s[i] - 0);}if (!isdigit(s[i]) &&am…

【智能制造-14】機器視覺軟件

CCD相機和COMS相機? CCD&#xff08;Charge-Coupled Device&#xff09;相機和CMOS&#xff08;Complementary Metal-Oxide-Semiconductor&#xff09;相機是兩種常見的數字圖像傳感器技術&#xff0c;用于捕捉和處理圖像。 CCD相機&#xff1a; CCD相機使用一種稱為CCD的光電…

北方論叢期刊

《北方論叢》投稿指南 為適應學術期刊文獻信息傳播現代化的需要&#xff0c;全面提高期刊質量&#xff0c;擴大學術交流&#xff0c;根據《中國學術期刊(光盤版)檢索與評價數據規范》《中國高等學校社會科學學報編排規范》以及其他國家標準和法規文件&#xff0c;并結合《北方論…

如何用webpack來優化前端性能?

Webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。它通過分析你的項目結構&#xff0c;找到 JavaScript 模塊以及其它的一些瀏覽器不能直接運行的拓展語言&#xff08;如SCSS, TypeScript等&#xff09;&#xff0c;并將其轉換和打包為合適的格式供瀏…

數據分析入門指南:表結構數據(三)

在數字化轉型的浪潮中&#xff0c;表結構數據作為企業決策支持系統的核心要素&#xff0c;其重要性日益凸顯。本文深入剖析了表結構數據的本質特征、高效處理策略&#xff0c;并探討了其在現代商業智能環境中的廣泛應用&#xff0c;旨在為數據分析師與決策者提供前沿洞察與實戰…

人工智能算法工程師(中級)課程3-sklearn機器學習之數據處理與代碼詳解

大家好&#xff0c;我是微學AI,今天給大家分享一下人工智能算法工程師(中級)課程3-sklearn機器學習之數據處理與代碼詳解。 Sklearn&#xff08;Scikit-learn&#xff09;是一個基于Python的開源機器學習庫&#xff0c;它提供了簡單有效的數據挖掘和數據分析工具。Sklearn包含了…

華為HCIP Datacom H12-821 卷34

1.單選題 防火墻默認已經創建了一些安全區域,以下哪一個安全區域不是防火墻上默認存在的? A、Trust B、DMZ C、Internet D、Local 正確答案&#xff1a; C 解析&#xff1a; 防火墻默認情況下為我們提供了三個安全區域&#xff0c;分別是 Trust、DMZ和Untrust 2.判斷題 …

電腦快捷鍵:提升效率的秘密武器

在現代社會中&#xff0c;電腦已經成為我們生活中不可或缺的工具。然而&#xff0c;要想充分利用電腦的功能&#xff0c;熟練掌握一些快捷鍵是必不可少的。本文將為您介紹一些常用的電腦快捷鍵&#xff0c;幫助您提高工作效率&#xff0c;節省寶貴的時間。 Windows 系統快捷鍵 …

【國產開源可視化引擎Meta2d.js】鷹眼地圖

鷹眼地圖 畫布右下角彈出一個縮略導航地圖&#xff0c;鼠標點擊可以跳到指定位置。 在線體驗&#xff1a; 樂吾樂2D可視化 示例&#xff1a; // 顯示縮略地圖 meta2d.showMap();// 關閉縮略地圖 meta2d.hideMap();

樹形結構的一種便捷實現方案

背景 在開發過程中經常需要把平鋪的數據結構轉為樹形的數據結構&#xff0c;例如多級菜單、組織機構等。 實現方案有很多種。 1、可以使用遞歸查詢&#xff0c;但是這樣數據一多會導致頻繁的多次查詢數據庫&#xff0c;產生很多額外的IO開銷&#xff0c;總體的響應時間會比較…

【uniapp微信小程序】uniapp微信小程序——頁面通信

uniapp微信小程序——頁面通信 在開發微信小程序過程中&#xff0c;頁面之間的通信是一個常見需求。在使用 uniapp 開發微信小程序時&#xff0c;我們可以采用多種方式實現頁面之間的數據傳遞和狀態共享。本文將詳細介紹幾種常見的實現方式&#xff0c;以供開發者參考。 1. 頁…