當前位置:
首頁 > 最新 > Andoird優化,內存優化

Andoird優化,內存優化

內存管理

但這也僅僅是為大家提供一些思路與較為全面的總結,算不上什麼,希望有錯誤或問題在下面評論。

最後完結以後會將思維導圖與優化框架整理出來,請期待。

如果程序會運行著崩潰、或者突然被系統殺死,那你就該繼續往下看。

這是這章的思維導圖,不過壓縮嚴重,下面是樣圖,原圖和源文件在最下方鏈接。還是值得下載的。

題記

應用的生存期絕大部分時間都用於處理內存中的數據,雖然我們大多數人都意識到在手機上要儘可能少使用內存,但並非所有人都認識到了內存使用對性能的影響。所以,下面我們來討論一下。


一、談談移動設備中的內存

無論分配給應用多少內存,它都不會滿足。

移動設備和傳統的電腦有兩個很大的差異;

物理內存大小

虛擬內存交換能力

要在一定設備上使用儘可能少的內存,既是經驗也是常識。

好處:

減少碰到oom異常的風險

提升性能

性能取決於以下三個因素( 我們會在下面講解)

CPU如何操縱特定的數據類型

數據和指令需要佔用多少存儲空間


二、採用合適的數據類型

使用long比short和int慢

同樣,只使用double及混用float和double,比只用float慢。

注意:由於並不是所有指令的執行時間都相同,再加上cpu很複雜,所以並不能推測出具體的時間。 short數組排序遠比其他類型數組快

原因: short使用計數排序,演算法複雜度是線性的 而int和long使用快速排序演算法

處理64位類型(long或double)比處理32位類型慢

總的來說,

就是:

1、處理大量數據時,使用可以滿足要求的最小數據類型

2、避免類型轉換。盡量保持類型一致,儘可能在計算中使用單一類型。

3、如果有必要取得更好的性能,推倒重來,但要認真處理。


三、你需要知道的訪問內存

1、操縱較大類型的數據代價較高,因為用到了指令較多。 直觀的來說,指令越多性能越差,CPU需要做很多額外的工作

2、此外、代碼和數據都駐留在內存中,訪問內存本身也有開銷。 因為訪問內存會產生一些開銷,CPU會把最近訪問的內容緩存起來,無論是內存讀還是寫。

3、CPU通常使用兩級緩存或者三級緩存:

一級緩存

二級緩存

三級緩存(一般用於伺服器機或遊戲機器)

4、當數據或指令在緩存中找不到時,就是緩存未命中。這是需要從內存中讀取數據或指令。

緩存未命中幾種情況:

指令緩存讀未命中

數據緩存讀未命中

寫未命中

注意:第一種緩存未命中最關鍵,因為CPU要一直等到從內存中讀出指令,才可以繼續執行。

另外:現代CPU都能夠自動預取內存,為了避免或者只說是限制了緩存未命中情況的發生。


四、通過垃圾收集管理內存

1、Java的一個非常重要的優點是垃圾收集

原理: 不再使用的對象內存會被垃圾收集器釋放(回收)。

注意:還是會出現內存泄露的情況。

垃圾收集器會幫你管理內存,它做的不僅僅是釋放不用的內存。

2、內存泄漏:

只有當某個對象不再被引用時,它的內存才會被回收,當該被釋放的對象引用仍然存在時就會發生內存泄漏。

一個典型例子就是,由於屏幕旋轉,整個Activity對象會有泄露 很嚴重!因為Activity對象佔用相當多內存。

3、 避免內存泄漏方案。(大多數只能用來分析,並不會告訴你是否內存泄漏)

DDMS視圖裡面的Heap與Tracker 可以跟蹤內存使用和分配情況。 AS裡面的monitor 有內存、網路、等四個視圖

StrictMode類 會將檢測到的違規操作,將結果寫到日誌中。 只能用來分析,並不會告訴你是否內存泄漏

OneAPM 用過,並且也去面試過,很不錯。

五、通過Java中的引用來更好的管理

1、內存釋放是垃圾收集器的一個重要的特性,在垃圾收集器中它的作用比在內存管理系統中大得多。

2、Java定義了4中類型的引用

強(Strong):

其實就是普通的創建對象,保持無用對象的強引用可能會導致內存泄漏

軟(Soft):

其實軟引用和弱引用在本質上是類似的,軟引用適用於緩存,它可以自動刪除緩存中的條目

弱(Weak)

保障下次垃圾回收時基本會收走

虛(Phantom)

幾乎很少用到

3、當需要緩存或映射時,你不必實現類似的內存管理系統。精心規劃引用後,大部分工作可以放心地交給垃圾收集器完成。

4、 垃圾收集

垃圾收集可能會再不定的時間觸發,你幾乎無法控制它的時機。

但是有時,你可以通過System.gc( );提醒一下Android,

雖然如此,垃圾收集機制發生時間最終時間是不由你確定的。

5、 垃圾收集發生在應用的主線程,所以:

很可能降低響應速度和性能。

在及時遊戲中會出現丟幀,因為有太多時間花在垃圾收集上。

Andorid2.3有了轉機,垃圾收集工作轉移到了一個單獨的線程。比以前的Android版本好太多了


六、通過系統的API可以了解、管理內存

1、 Android定義了幾個API,你可以用他們來了解系統中還剩多少可用內存和用了多少內存

ActivityManager的:

getMomoryInfo() getMomoryClass() getLargeMeoryClass()

Debug的

dumpHprofData() getNativeHeapAllocatedSize() getNativeHeapSize()

提示:

在應用的manifest文件中把android:largeHeap設為true,就可以讓應用使用更大的堆。


七、當內存少的時候可以這樣處理

ComponentCallbacks介面定義了API onLowMomory( ),它對所有應用組> 件都是相同的。當它被調用時,組件基本會被要求釋放那些並不會用到的內存。

可以被釋放的內容:

緩存或緩存條目(如使用強引用的LruCache)

可以再次按需生成的點陣圖對象

不可見的布局對象

資料庫對象


八、通過5R法來對ANDROID內存進行優化:

首先需要知道你的app所消耗內存的情況,知己知彼才能百戰不殆

通過上文提到的工具進行查看消耗,這裡再給大家推薦一個工具

Memory Analysis Tool(MAT):

可以轉換成餅圖和表格,直觀、好用。


Reduce的意思就是減少,直接減少內存的使用是最有效的優化方式。

例如:

Bitmap:

Bitmap是內存消耗大戶,絕大多數的OOM崩潰都是在操作Bitmap時產生的,下面來看看幾個處理圖片的方法:

圖片顯示:

例如在列表中僅用於預覽時載入縮略圖(thumbnails )。

只有當用戶點擊具體條目想看詳細信息的時候,這時另啟動一個fragment/activity/對話框等等,去顯示整個圖片

圖片大小:

使用BitmapFactory.Options設置inSampleSize, 這樣做可以減少對系統資源的要求。

BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options(); bitmapFactoryOptions.inJustDecodeBounds = true; bitmapFactoryOptions.inSampleSize = 2; // 這裡一定要將其設置回false,因為之前我們將其設置成了true // 設置inJustDecodeBounds為true後,decodeFile並不分配空間,即,BitmapFactory解碼出來的Bitmap為Null,但可計算出原始圖片的長度和寬度 options.inJustDecodeBounds = false; Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap, options);

圖片像素:

Android中圖片有四種屬性,分別是:

ALPHA_8:每個像素佔用1byte內存

ARGB_4444:每個像素佔用2byte內存

ARGB_8888:每個像素佔用4byte內存 (默認)

RGB_565:每個像素佔用2byte內存

Android默認的顏色模式為ARGB_8888,這個顏色模式色彩最細膩,顯示質量最高。但同樣的,佔用的內存也最大。 所以在對圖片效果不是特別高的情況下使用RGB_565(565沒有透明度屬性),如下:

public static BitmapreadBitMap(Contextcontext, intresId) { BitmapFactory.Optionsopt = newBitmapFactory.Options(); opt.inPreferredConfig = Bitmap.Config.RGB_565; opt.inPurgeable = true; opt.inInputShareable = true; //獲取資源圖片 InputStream is = context.getResources().openRawResource(resId); return BitmapFactory.decodeStream(is, null, opt); }

圖片回收:

使用Bitmap過後,就需要及時的調用Bitmap.recycle()方法來釋放Bitmap佔用的內存空間,而不要等Android系統來進行釋放。

bitmap.recycle(); bitmap = null;

捕獲異常:

Bitmap bitmap = null; try { // 實例化Bitmap bitmap = BitmapFactory.decodeFile(path); } catch (OutOfMemoryError e) { // 捕獲OutOfMemoryError,避免直接崩潰 } if (bitmap == null) { // 如果實例化失敗 返回默認的Bitmap對象 return defaultBitmapMap; }

修改引用:

如果只是想避免OutOfMemory異常的發生,則可以使用軟引用。如果對於應用的性能更在意,想儘快回收一些佔用內存比較大的對象,則可以使用弱引用。

另外,和弱引用功能類似的是WeakHashMap。WeakHashMap對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的回收,回收以後,其條目從映射中有效地移除。WeakHashMap使用ReferenceQueue實現的這種機制。


核心思路就是將已經存在的內存資源重新使用而避免去創建新的,最典型的使用就是緩存(Cache)和池(Pool)。


Thread(線程)回收:

Cursor(游標)回收:

@Override protected void onDestroy() { if (mAdapter != null && mAdapter.getCurosr() != null) { mAdapter.getCursor().close(); } super.onDestroy(); }

還有接收器、流等等。


Code Review(代碼檢查):

Code Review主要檢查代碼中存在的一些不合理或可以改進優化的地方,

UI Review(視圖檢查):

Android對於視圖中控制項的布局渲染等會消耗很多的資源和內存,所以這部分也是我們需要注意的。

減少視圖層級:

減少視圖層級可以有效的減少內存消耗,因為視圖是一個樹形結構,每次刷新和渲染都會遍歷一次。

hierarchyviewer:

想要減少視圖層級首先就需要知道視圖層級,所以下面介紹一個SDK中自帶的一個非常好用的工具hierarchyviewer。

你可以在下面的地址找到它:your sdk pathsdk ools


總結

刪除對象應該仔細考慮,因為重新創建是需要開銷的。

如果沒有釋放出足夠的內存可能會導致Android系統更激進的行為(如殺死進程)。

如果應用進程被殺掉了,用戶下次使用又要從頭開始。因此,應用不僅要表現出色,也要釋放儘可能多的資源。 代碼中推遲初始化是一個好的方式。

內存在嵌入式設備上是稀缺資源。儘管今天的手機和平板電腦的內存越來越多, 但這些設備也在運行越來越複雜的系統和應用。有效的使用內存, 不僅可以使應用在舊設備上運行時佔用較少的內存, 還可以讓程序跑的更快。請記住,應用對內存的需求是無止境的。

Anroid優化(二)_內存優化.xmind 下載:http://pan.baidu.com/s/1hsK2Co0 密碼:abcs

來自:http://www.jianshu.com/p/afd4d8a6dcd6


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 殘殤 的精彩文章:

Android圖片載入框架最全解析二,從源碼的角度理解Glide的執行流程

TAG:殘殤 |