Andoird優化,內存優化

laura107 8年前發布 | 35K 次閱讀 Android Android開發 移動開發

Andoird優化,內存優化

內存管理

 

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

最后完結以后會將思維導圖與優化框架整理出來,請期待。
如果程序會運行著崩潰、或者突然被系統殺死,那你就該繼續往下看。

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內存進行優化:

1.Reckon(計算)

首先需要知道你的app所消耗內存的情況,知己知彼才能百戰不殆
通過上文提到的工具進行查看消耗,這里再給大家推薦一個工具
Memory Analysis Tool(MAT):
可以轉換成餅圖和表格,直觀、好用。

2.Reduce(減少)

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實現的這種機制。

3.Reuse(重用)

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

4.Recycle(回收)

Thread(線程)回收:

Thread t = new Thread() {  
     public void run() {  
         while (true) {  
             try {  
                 Thread.sleep(1000);  
                 System.out.println("thread is running...");  
             } catch (InterruptedException e) {  

             }  
        }  
     }  
 };  
 t.start();  
 t = null;  
 System.gc();

Cursor(游標)回收:

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

還有接收器、流等等。

5.Review(檢查)

Code Review(代碼檢查):

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

UI Review(視圖檢查):

Android對于視圖中控件的布局渲染等會消耗很多的資源和內存,所以這部分也是我們需要注意的。
減少視圖層級:
減少視圖層級可以有效的減少內存消耗,因為視圖是一個樹形結構,每次刷新和渲染都會遍歷一次。

hierarchyviewer

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

你可以在下面的地址找到它:your sdk path\sdk\tools

總結

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

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

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

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

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


 

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

 本文由用戶 laura107 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!