一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

ANDROID內(nèi)存優(yōu)化(大匯總

 深呼吸_DA 2014-10-11

轉(zhuǎn)載請注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),謝謝支持!


寫在最前:

本文的思路主要借鑒了2014年AnDevCon開發(fā)者大會(huì)的一個(gè)演講PPT,加上把網(wǎng)上搜集的各種內(nèi)存零散知識(shí)點(diǎn)進(jìn)行匯總、挑選、簡化后整理而成。

所以我將本文定義為一個(gè)工具類的文章,如果你在ANDROID開發(fā)中遇到關(guān)于內(nèi)存問題,或者馬上要參加面試,或者就是單純的學(xué)習(xí)或復(fù)習(xí)一下內(nèi)存相關(guān)知識(shí),都?xì)g迎閱讀。(本文最后我會(huì)盡量列出所參考的文章)。


OOM:


內(nèi)存泄露可以引發(fā)很多的問題:

1.程序卡頓,響應(yīng)速度慢(內(nèi)存占用高時(shí)JVM虛擬機(jī)會(huì)頻繁觸發(fā)GC)

2.莫名消失(當(dāng)你的程序所占內(nèi)存越大,它在后臺(tái)的時(shí)候就越可能被干掉。反之內(nèi)存占用越小,在后臺(tái)存在的時(shí)間就越長)

3.直接崩潰(OutOfMemoryError)


ANDROID內(nèi)存面臨的問題:

1.有限的堆內(nèi)存,原始只有16M

2.內(nèi)存大小消耗等根據(jù)設(shè)備,操作系統(tǒng)等級,屏幕尺寸的不同而不同

3.程序不能直接控制

4.支持后臺(tái)多任務(wù)處理(multitasking)

5.運(yùn)行在虛擬機(jī)之上


5R:

本文主要通過如下的5R方法來對ANDROID內(nèi)存進(jìn)行優(yōu)化:


1.Reckon(計(jì)算)

首先需要知道你的app所消耗內(nèi)存的情況,知己知彼才能百戰(zhàn)不殆

2.Reduce(減少)

消耗更少的資源

3.Reuse(重用)

當(dāng)?shù)谝淮问褂猛暌院?,盡量給其他的使用

5.Recycle(回收)

回收資源

4.Review(檢查)

回顧檢查你的程序,看看設(shè)計(jì)或代碼有什么不合理的地方。



Reckon:


關(guān)于內(nèi)存簡介,和Reckon(內(nèi)存計(jì)算)的內(nèi)容請看上一篇文章:ANDROID內(nèi)存優(yōu)化(大匯總——上)



Reduce :


Reduce的意思就是減少,直接減少內(nèi)存的使用是最有效的優(yōu)化方式。

下面來看看有哪些方法可以減少內(nèi)存使用:


Bitmap
Bitmap是內(nèi)存消耗大戶,絕大多數(shù)的OOM崩潰都是在操作Bitmap時(shí)產(chǎn)生的,下面來看看幾個(gè)處理圖片的方法:


圖片顯示:

我們需要根據(jù)需求去加載圖片的大小。

例如在列表中僅用于預(yù)覽時(shí)加載縮略圖(thumbnails )。

只有當(dāng)用戶點(diǎn)擊具體條目想看詳細(xì)信息的時(shí)候,這時(shí)另啟動(dòng)一個(gè)fragment/activity/對話框等等,去顯示整個(gè)圖片


圖片大?。?/span>

直接使用ImageView顯示bitmap會(huì)占用較多資源,特別是圖片較大的時(shí)候,可能導(dǎo)致崩潰。 
使用BitmapFactory.Options設(shè)置inSampleSize, 這樣做可以減少對系統(tǒng)資源的要求。 
屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個(gè)值為2,則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。 

  1. BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();  
  2. bitmapFactoryOptions.inJustDecodeBounds = true;  
  3. bitmapFactoryOptions.inSampleSize = 2;  
  4. // 這里一定要將其設(shè)置回false,因?yàn)橹拔覀儗⑵湓O(shè)置成了true    
  5. // 設(shè)置inJustDecodeBounds為true后,decodeFile并不分配空間,即,BitmapFactory解碼出來的Bitmap為Null,但可計(jì)算出原始圖片的長度和寬度    
  6. options.inJustDecodeBounds = false;  
  7. Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap, options);  


圖片像素:

Android中圖片有四種屬性,分別是:
ALPHA_8:每個(gè)像素占用1byte內(nèi)存 
ARGB_4444:每個(gè)像素占用2byte內(nèi)存 
ARGB_8888:每個(gè)像素占用4byte內(nèi)存 (默認(rèn))
RGB_565:每個(gè)像素占用2byte內(nèi)存 

Android默認(rèn)的顏色模式為ARGB_8888,這個(gè)顏色模式色彩最細(xì)膩,顯示質(zhì)量最高。但同樣的,占用的內(nèi)存也最大。 所以在對圖片效果不是特別高的情況下使用RGB_565(565沒有透明度屬性),如下:
  1. publicstaticBitmapreadBitMap(Contextcontext, intresId) {  
  2.     BitmapFactory.Optionsopt = newBitmapFactory.Options();  
  3.     opt.inPreferredConfig = Bitmap.Config.RGB_565;  
  4.     opt.inPurgeable = true;  
  5.     opt.inInputShareable = true;  
  6.     //獲取資源圖片   
  7.     InputStreamis = context.getResources().openRawResource(resId);  
  8.     returnBitmapFactory.decodeStream(is, null, opt);  
  9. }  

圖片回收:

使用Bitmap過后,就需要及時(shí)的調(diào)用Bitmap.recycle()方法來釋放Bitmap占用的內(nèi)存空間,而不要等Android系統(tǒng)來進(jìn)行釋放。

下面是釋放Bitmap的示例代碼片段。

  1. // 先判斷是否已經(jīng)回收  
  2. if(bitmap != null && !bitmap.isRecycled()){  
  3.     // 回收并且置為null  
  4.     bitmap.recycle();  
  5.     bitmap = null;  
  6. }  
  7. System.gc();  

捕獲異常:

經(jīng)過上面這些優(yōu)化后還會(huì)存在報(bào)OOM的風(fēng)險(xiǎn),所以下面需要一道最后的關(guān)卡——捕獲OOM異常:

  1. Bitmap bitmap = null;  
  2. try {  
  3.     // 實(shí)例化Bitmap  
  4.     bitmap = BitmapFactory.decodeFile(path);  
  5. } catch (OutOfMemoryError e) {  
  6.     // 捕獲OutOfMemoryError,避免直接崩潰  
  7. }  
  8. if (bitmap == null) {  
  9.     // 如果實(shí)例化失敗 返回默認(rèn)的Bitmap對象  
  10.     return defaultBitmapMap;  
  11. }  



修改對象引用類型:


引用類型:

引用分為四種級別,這四種級別由高到低依次為:強(qiáng)引用>軟引用>弱引用>虛引用。

強(qiáng)引用(strong reference)
如:Object object=new Object(),object就是一個(gè)強(qiáng)引用了。當(dāng)內(nèi)存空間不足,Java虛擬機(jī)寧愿拋出OutOfMemoryError錯(cuò)誤,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對象來解決內(nèi)存不足問題。

軟引用(SoftReference)
只有內(nèi)存不夠時(shí)才回收,常用于緩存;當(dāng)內(nèi)存達(dá)到一個(gè)閥值,GC就會(huì)去回收它;

弱引用(WeakReference)   

弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它 所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象,不管當(dāng)前內(nèi)存空間足夠與否,都會(huì)回收它的內(nèi)存。 


虛引用(PhantomReference)   

"虛引用"顧名思義,就是形同虛設(shè),與其他幾種引用都不同,虛引用并不會(huì)決定對象的生命周期。如果一個(gè)對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時(shí)候都可能被垃圾回收。  


軟引用和弱引用的應(yīng)用實(shí)例:

注意:對于SoftReference(軟引用)或者WeakReference(弱引用)的Bitmap緩存方案,現(xiàn)在已經(jīng)不推薦使用了。自Android2.3版本(API Level 9)開始,垃圾回收器更著重于對軟/弱引用的回收,所以下面的內(nèi)容可以選擇忽略。

在Android應(yīng)用的開發(fā)中,為了防止內(nèi)存溢出,在處理一些占用內(nèi)存大而且聲明周期較長的對象時(shí)候,可以盡量應(yīng)用軟引用和弱引用技術(shù)。

下面以使用軟引用為例來詳細(xì)說明(弱引用的使用方式與軟引用是類似的):

假設(shè)我們的應(yīng)用會(huì)用到大量的默認(rèn)圖片,而且這些圖片很多地方會(huì)用到。如果每次都去讀取圖片,由于讀取文件需要硬件操作,速度較慢,會(huì)導(dǎo)致性能較低。所以我們考慮將圖片緩存起來,需要的時(shí)候直接從內(nèi)存中讀取。但是,由于圖片占用內(nèi)存空間比較大,緩存很多圖片需要很多的內(nèi)存,就可能比較容易發(fā)生OutOfMemory異常。這時(shí),我們可以考慮使用軟引用技術(shù)來避免這個(gè)問題發(fā)生。

首先定義一個(gè)HashMap,保存軟引用對象。

  1. private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();  
再來定義一個(gè)方法,保存Bitmap的軟引用到HashMap。

  1. public void addBitmapToCache(String path) {  
  2.        // 強(qiáng)引用的Bitmap對象  
  3.        Bitmap bitmap = BitmapFactory.decodeFile(path);  
  4.        // 軟引用的Bitmap對象  
  5.        SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);  
  6.        // 添加該對象到Map中使其緩存  
  7.        imageCache.put(path, softBitmap);  
  8.    }  
獲取的時(shí)候,可以通過SoftReference的get()方法得到Bitmap對象。
  1. public Bitmap getBitmapByPath(String path) {  
  2.         // 從緩存中取軟引用的Bitmap對象  
  3.         SoftReference<Bitmap> softBitmap = imageCache.get(path);  
  4.         // 判斷是否存在軟引用  
  5.         if (softBitmap == null) {  
  6.             return null;  
  7.         }  
  8.         // 取出Bitmap對象,如果由于內(nèi)存不足Bitmap被回收,將取得空  
  9.         Bitmap bitmap = softBitmap.get();  
  10.         return bitmap;  
  11.     }  
使用軟引用以后,在OutOfMemory異常發(fā)生之前,這些緩存的圖片資源的內(nèi)存空間可以被釋放掉的,從而避免內(nèi)存達(dá)到上限,避免Crash發(fā)生。

需要注意的是,在垃圾回收器對這個(gè)Java對象回收前,SoftReference類所提供的get方法會(huì)返回Java對象的強(qiáng)引用,一旦垃圾線程回收該Java對象之后,get方法將返回null。所以在獲取軟引用對象的代碼中,一定要判斷是否為null,以免出現(xiàn)NullPointerException異常導(dǎo)致應(yīng)用崩潰。


到底什么時(shí)候使用軟引用,什么時(shí)候使用弱引用呢?

個(gè)人認(rèn)為,如果只是想避免OutOfMemory異常的發(fā)生,則可以使用軟引用。如果對于應(yīng)用的性能更在意,想盡快回收一些占用內(nèi)存比較大的對象,則可以使用弱引用。

還有就是可以根據(jù)對象是否經(jīng)常使用來判斷。如果該對象可能會(huì)經(jīng)常使用的,就盡量用軟引用。如果該對象不被使用的可能性更大些,就可以用弱引用。

另外,和弱引用功能類似的是WeakHashMap。WeakHashMap對于一個(gè)給定的鍵,其映射的存在并不阻止垃圾回收器對該鍵的回收,回收以后,其條目從映射中有效地移除。WeakHashMap使用ReferenceQueue實(shí)現(xiàn)的這種機(jī)制。


其他小tips:

對常量使用static final修飾符

讓我們來看看這兩段在類前面的聲明:

static int intVal = 42;
static String strVal = "Hello, world!";
編譯器會(huì)生成一個(gè)叫做clinit的初始化類的方法,當(dāng)類第一次被使用的時(shí)候這個(gè)方法會(huì)被執(zhí)行。方法會(huì)將42賦給intVal,然后把一個(gè)指向類中常量表 的引用賦給strVal。當(dāng)以后要用到這些值的時(shí)候,會(huì)在成員變量表中查找到他們。 下面我們做些改進(jìn),使用“final”關(guān)鍵字:

static final int intVal = 42;
static final String strVal = "Hello, world!";

現(xiàn)在,類不再需要clinit方法,因?yàn)樵诔蓡T變量初始化的時(shí)候,會(huì)將常量直接保存到類文件中。用到intVal的代碼被直接替換成42,而使用strVal的會(huì)指向一個(gè)字符串常量,而不是使用成員變量。

將一個(gè)方法或類聲明為final不會(huì)帶來性能的提升,但是會(huì)幫助編譯器優(yōu)化代碼。舉例說,如果編譯器知道一個(gè)getter方法不會(huì)被重載,那么編譯器會(huì)對其采用內(nèi)聯(lián)調(diào)用。

你也可以將本地變量聲明為final,同樣,這也不會(huì)帶來性能的提升。使用“final”只能使本地變量看起來更清晰些(但是也有些時(shí)候這是必須的,比如在使用匿名內(nèi)部類的時(shí)候)。

靜態(tài)方法代替虛擬方法

如果不需要訪問某對象的字段,將方法設(shè)置為靜態(tài),調(diào)用會(huì)加速15%到20%。這也是一種好的做法,因?yàn)槟憧梢詮姆椒暶髦锌闯稣{(diào)用該方法不需要更新此對象的狀態(tài)。


減少不必要的全局變量

盡量避免static成員變量引用資源耗費(fèi)過多的實(shí)例,比如Context

因?yàn)镃ontext的引用超過它本身的生命周期,會(huì)導(dǎo)致Context泄漏。所以盡量使用Application這種Context類型。 你可以通過調(diào)用Context.getApplicationContext()或 Activity.getApplication()輕松得到Application對象。 

避免創(chuàng)建不必要的對象

最常見的例子就是當(dāng)你要頻繁操作一個(gè)字符串時(shí),使用StringBuffer代替String。

對于所有所有基本類型的組合:int數(shù)組比Integer數(shù)組好,這也概括了一個(gè)基本事實(shí),兩個(gè)平行的int數(shù)組比 (int,int)對象數(shù)組性能要好很多。

總體來說,就是避免創(chuàng)建短命的臨時(shí)對象。減少對象的創(chuàng)建就能減少垃圾收集,進(jìn)而減少對用戶體驗(yàn)的影響。


避免內(nèi)部Getters/Setters
在Android中,虛方法調(diào)用的代價(jià)比直接字段訪問高昂許多。通常根據(jù)面向?qū)ο笳Z言的實(shí)踐,在公共接口中使用Getters和Setters是有道理的,但在一個(gè)字段經(jīng)常被訪問的類中宜采用直接訪問。

避免使用浮點(diǎn)數(shù)

通常的經(jīng)驗(yàn)是,在Android設(shè)備中,浮點(diǎn)數(shù)會(huì)比整型慢兩倍。


使用實(shí)體類比接口好

假設(shè)你有一個(gè)HashMap對象,你可以將它聲明為HashMap或者M(jìn)ap:

Map map1 = new HashMap();
HashMap map2 = new HashMap();

哪個(gè)更好呢?

按照傳統(tǒng)的觀點(diǎn)Map會(huì)更好些,因?yàn)檫@樣你可以改變他的具體實(shí)現(xiàn)類,只要這個(gè)類繼承自Map接口。傳統(tǒng)的觀點(diǎn)對于傳統(tǒng)的程序是正確的,但是它并不適合嵌入式系統(tǒng)。調(diào)用一個(gè)接口的引用會(huì)比調(diào)用實(shí)體類的引用多花費(fèi)一倍的時(shí)間。如果HashMap完全適合你的程序,那么使用Map就沒有什么價(jià)值。如果有些地方你不能確定,先避免使用Map,剩下的交給IDE提供的重構(gòu)功能好了。(當(dāng)然公共API是一個(gè)例外:一個(gè)好的API常常會(huì)犧牲一些性能)


避免使用枚舉

枚舉變量非常方便,但不幸的是它會(huì)犧牲執(zhí)行的速度和并大幅增加文件體積。

使用枚舉變量可以讓你的API更出色,并能提供編譯時(shí)的檢查。所以在通常的時(shí)候你毫無疑問應(yīng)該為公共API選擇枚舉變量。但是當(dāng)性能方面有所限制的時(shí)候,你就應(yīng)該避免這種做法了。


for循環(huán)

訪問成員變量比訪問本地變量慢得多,如下面一段代碼:

  1. for(int i =0; i < this.mCount; i++)  {}  

永遠(yuǎn)不要在for的第二個(gè)條件中調(diào)用任何方法,如下面一段代碼:

  1. for(int i =0; i < this.getCount(); i++) {}  

對上面兩個(gè)例子最好改為:

  1. int count = this.mCount; / int count = this.getCount();  
  2. for(int i =0; i < count; i++)  {}  
在java1.5中引入的for-each語法。編譯器會(huì)將對數(shù)組的引用和數(shù)組的長度保存到本地變量中,這對訪問數(shù)組元素非常好。 但是編譯器還會(huì)在每次循環(huán)中產(chǎn)生一個(gè)額外的對本地變量的存儲(chǔ)操作(如下面例子中的變量a),這樣會(huì)比普通循環(huán)多出4個(gè)字節(jié),速度要稍微慢一些:

  1. for (Foo a : mArray) {  
  2.     sum += a.mSplat;  
  3. }  

了解并使用類庫

選擇Library中的代碼而非自己重寫,除了通常的那些原因外,考慮到系統(tǒng)空閑時(shí)會(huì)用匯編代碼調(diào)用來替代library方法,這可能比JIT中生成的等價(jià)的最好的Java代碼還要好。

當(dāng)你在處理字串的時(shí)候,不要吝惜使用String.indexOf(),String.lastIndexOf()等特殊實(shí)現(xiàn)的方法。這些方法都是使用C/C++實(shí)現(xiàn)的,比起Java循環(huán)快10到100倍。

System.arraycopy方法在有JIT的Nexus One上,自行編碼的循環(huán)快9倍。

android.text.format包下的Formatter類,提供了IP地址轉(zhuǎn)換、文件大小轉(zhuǎn)換等方法;DateFormat類,提供了各種時(shí)間轉(zhuǎn)換,都是非常高效的方法。

TextUtils類,對于字符串處理Android為我們提供了一個(gè)簡單實(shí)用的TextUtils類,如果處理比較簡單的內(nèi)容不用去思考正則表達(dá)式不妨試試這個(gè)在android.text.TextUtils的類

高性能MemoryFile類,很多人抱怨Android處理底層I/O性能不是很理想,如果不想使用NDK則可以通過MemoryFile類實(shí)現(xiàn)高性能的文件讀寫操作。MemoryFile適用于哪些地方呢?對于I/O需要頻繁操作的,主要是和外部存儲(chǔ)相關(guān)的I/O操作,MemoryFile通過將 NAND或SD卡上的文件,分段映射到內(nèi)存中進(jìn)行修改處理,這樣就用高速的RAM代替了ROM或SD卡,性能自然提高不少,對于Android手機(jī)而言同時(shí)還減少了電量消耗。該類實(shí)現(xiàn)的功能不是很多,直接從Object上繼承,通過JNI的方式直接在C底層執(zhí)行。



Reuse:


Reuse重用,減少內(nèi)存消耗的重要手段之一。
核心思路就是將已經(jīng)存在的內(nèi)存資源重新使用而避免去創(chuàng)建新的,最典型的使用就是緩存(Cache池(Pool)

Bitmap緩存:

Bitmap緩存分為兩種:

一種是內(nèi)存緩存,一種是硬盤緩存。


內(nèi)存緩存(LruCache):

以犧牲寶貴的應(yīng)用內(nèi)存為代價(jià),內(nèi)存緩存提供了快速的Bitmap訪問方式。系統(tǒng)提供的LruCache類是非常適合用作緩存Bitmap任務(wù)的,它將最近被引用到的對象存儲(chǔ)在一個(gè)強(qiáng)引用的LinkedHashMap中,并且在緩存超過了指定大小之后將最近不常使用的對象釋放掉。

注意以前有一個(gè)非常流行的內(nèi)存緩存實(shí)現(xiàn)是SoftReference(軟引用)或者WeakReference(弱引用)的Bitmap緩存方案,然而現(xiàn)在已經(jīng)不推薦使用了。自Android2.3版本(API Level 9)開始,垃圾回收器更著重于對軟/弱引用的回收,這使得上述的方案相當(dāng)無效。


硬盤緩存(DiskLruCache):

一個(gè)內(nèi)存緩存對加速訪問最近瀏覽過的Bitmap非常有幫助,但是你不能局限于內(nèi)存中的可用圖片。GridView這樣有著更大的數(shù)據(jù)集的組件可以很輕易消耗掉內(nèi)存緩存。你的應(yīng)用有可能在執(zhí)行其他任務(wù)(如打電話)的時(shí)候被打斷,并且在后臺(tái)的任務(wù)有可能被殺死或者緩存被釋放。一旦用戶重新聚焦(resume)到你的應(yīng)用,你得再次處理每一張圖片。

在這種情況下,硬盤緩存可以用來存儲(chǔ)Bitmap并在圖片被內(nèi)存緩存釋放后減小圖片加載的時(shí)間(次數(shù))。當(dāng)然,從硬盤加載圖片比內(nèi)存要慢,并且應(yīng)該在后臺(tái)線程進(jìn)行,因?yàn)橛脖P讀取的時(shí)間是不可預(yù)知的。

注意:如果訪問圖片的次數(shù)非常頻繁,那么ContentProvider可能更適合用來存儲(chǔ)緩存圖片,例如Image Gallery這樣的應(yīng)用程序。

更多關(guān)于內(nèi)存緩存和硬盤緩存的內(nèi)容請看Google官方教程https://developer./develop/index.html

圖片緩存的開源項(xiàng)目:
對于圖片的緩存現(xiàn)在都傾向于使用開源項(xiàng)目,這里我列出幾個(gè)我搜到的:

1. Android-Universal-Image-Loader 圖片緩存

目前使用最廣泛的圖片緩存,支持主流圖片緩存的絕大多數(shù)特性。
項(xiàng)目地址:https://github.com/nostra13/Android-Universal-Image-Loader

 

2. picasso square開源的圖片緩存
項(xiàng)目地址:https://github.com/square/picasso
特點(diǎn):(1)可以自動(dòng)檢測adapter的重用并取消之前的下載
(2)圖片變換
(3)可以加載本地資源
(4)可以設(shè)置占位資源
(5)支持debug模式

 

3. ImageCache 圖片緩存,包含內(nèi)存和Sdcard緩存
項(xiàng)目地址:https://github.com/Trinea/AndroidCommon
特點(diǎn):

(1)支持預(yù)取新圖片,支持等待隊(duì)列
(2)包含二級緩存,可自定義文件名保存規(guī)則
(3)可選擇多種緩存算法(FIFO、LIFO、LRU、MRU、LFU、MFU等13種)或自定義緩存算法
(4)可方便的保存及初始化恢復(fù)數(shù)據(jù)
(5)支持不同類型網(wǎng)絡(luò)處理
(6)可根據(jù)系統(tǒng)配置初始化緩存等


4. Android 網(wǎng)絡(luò)通信框架Volley
項(xiàng)目地址:https://android./platform/frameworks/volley
我們在程序中需要和網(wǎng)絡(luò)通信的時(shí)候,大體使用的東西莫過于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,在2013年的Google I/O發(fā)布了Volley。Volley是Android平臺(tái)上的網(wǎng)絡(luò)通信庫,能使網(wǎng)絡(luò)通信更快,更簡單,更健壯。
特點(diǎn):
(1)JSON,圖像等的異步下載;
(2)網(wǎng)絡(luò)請求的排序(scheduling)
(3)網(wǎng)絡(luò)請求的優(yōu)先級處理
(4)緩存
(5)多級別取消請求
(6)和Activity和生命周期的聯(lián)動(dòng)(Activity結(jié)束時(shí)同時(shí)取消所有網(wǎng)絡(luò)請求)

Adapter適配器

在Android中Adapter使用十分廣泛,特別是在list中。所以adapter是數(shù)據(jù)的 “集散地” ,所以對其進(jìn)行內(nèi)存優(yōu)化是很有必要的。
下面算是一個(gè)標(biāo)準(zhǔn)的使用模版:
主要使用convertView和ViewHolder來進(jìn)行緩存處理

  1. @Override  
  2. public View getView(int position, View convertView, ViewGroup parent) {  
  3.     ViewHolder vHolder = null;  
  4.     //如果convertView對象為空則創(chuàng)建新對象,不為空則復(fù)用    
  5.     if (convertView == null) {  
  6.         convertView = inflater.inflate(..., null);  
  7.         // 創(chuàng)建 ViewHodler 對象    
  8.         vHolder = new ViewHolder();  
  9.         vHolder.img= (ImageView) convertView.findViewById(...);  
  10.         vHolder.tv= (TextView) convertView.findViewById(...);  
  11.         // 將ViewHodler保存到Tag中(Tag可以接收Object類型對象,所以任何東西都可以保存在其中)  
  12.         convertView.setTag(vHolder);  
  13.     } else {  
  14.         //當(dāng)convertView不為空時(shí),通過getTag()得到View    
  15.         vHolder = (ViewHolder) convertView.getTag();  
  16.     }  
  17.     // 給對象賦值,修改顯示的值    
  18.     vHolder.img.setImageBitmap(...);  
  19.     vHolder.tv.setText(...);  
  20.     return convertView;  
  21. }  
  22. //將顯示的View 包裝成類    
  23. static class ViewHolder {  
  24.     TextView tv;  
  25.     ImageView img;  
  26. }  


池(PooL)

對象池:

對象池使用的基本思路是:將用過的對象保存起來,等下一次需要這種對象的時(shí)候,再拿出來重復(fù)使用,從而在一定程度上減少頻繁創(chuàng)建對象所造成的開銷。 并非所有對象都適合拿來池化――因?yàn)榫S護(hù)對象池也要造成一定開銷。對生成時(shí)開銷不大的對象進(jìn)行池化,反而可能會(huì)出現(xiàn)“維護(hù)對象池的開銷”大于“生成新對象的開銷”,從而使性能降低的情況。但是對于生成時(shí)開銷可觀的對象,池化技術(shù)就是提高性能的有效策略了。


線程池:

線程池的基本思想還是一種對象池的思想,開辟一塊內(nèi)存空間,里面存放了眾多(未死亡)的線程,池中線程執(zhí)行調(diào)度由池管理器來處理。當(dāng)有線程任務(wù)時(shí),從池中取一個(gè),執(zhí)行完成后線程對象歸池,這樣可以避免反復(fù)創(chuàng)建線程對象所帶來的性能開銷,節(jié)省了系統(tǒng)的資源。

比如:一個(gè)應(yīng)用要和網(wǎng)絡(luò)打交道,有很多步驟需要訪問網(wǎng)絡(luò),為了不阻塞主線程,每個(gè)步驟都創(chuàng)建個(gè)線程,在線程中和網(wǎng)絡(luò)交互,用線程池就變的簡單,線程池是對線程的一種封裝,讓線程用起來更加簡便,只需要?jiǎng)?chuàng)一個(gè)線程池,把這些步驟像任務(wù)一樣放進(jìn)線程池,在程序銷毀時(shí)只要調(diào)用線程池的銷毀函數(shù)即可。


java提供了ExecutorServiceExecutors類,我們可以應(yīng)用它去建立線程池。

通??梢越⑷缦?種:

  1. /** 每次只執(zhí)行一個(gè)任務(wù)的線程池 */  
  2. ExecutorService singleTaskExecutor =  Executors.newSingleThreadExecutor();  
  3.   
  4. /** 每次執(zhí)行限定個(gè)數(shù)個(gè)任務(wù)的線程池 */  
  5. ExecutorService limitedTaskExecutor = Executors.newFixedThreadPool(3);  
  6.   
  7. /** 所有任務(wù)都一次性開始的線程池 */  
  8. ExecutorService allTaskExecutor = Executors.newCachedThreadPool();  
  9.   
  10. /** 創(chuàng)建一個(gè)可在指定時(shí)間里執(zhí)行任務(wù)的線程池,亦可重復(fù)執(zhí)行 */  
  11. ExecutorService scheduledTaskExecutor = Executors.newScheduledThreadPool(3);  


更多關(guān)于線程池的內(nèi)容我推薦這篇文章:http://www./archives/2439

注意:

要根據(jù)情況適度使用緩存,因?yàn)閮?nèi)存有限。

能保存路徑地址的就不要存放圖片數(shù)據(jù),不經(jīng)常使用的盡量不要緩存,不用時(shí)就清空。



寫在最后:

我準(zhǔn)備將文章分為上、中、下三部分?,F(xiàn)在已經(jīng)全部完成:

內(nèi)存簡介,Recoken(計(jì)算)請看ANDROID內(nèi)存優(yōu)化(大匯總——上)

Reduce(減少),Reuse(重用) 請看:ANDROID內(nèi)存優(yōu)化(大匯總——中)

Recycle(回收), Review(檢查) 請看:ANDROID內(nèi)存優(yōu)化(大匯總——全)


寫這篇文章的目的就是想弄一個(gè)大匯總,將零散的內(nèi)存知識(shí)點(diǎn)總結(jié)一下,如果有錯(cuò)誤、不足或建議都希望告訴我。



參考文章:

解析Android開發(fā)優(yōu)化之:軟引用與弱引用的應(yīng)用(http://www.jb51.net/article/36627.htm)
android內(nèi)存泄露優(yōu)化總結(jié)(http://blog.csdn.net/imain/article/details/8560986)
Android 內(nèi)存優(yōu)化(http://blog.csdn.net/awangyunke/article/details/20380719)
Android開發(fā)優(yōu)化之——對Bitmap的內(nèi)存優(yōu)化(http://blog.csdn.net/arui319/article/details/7953690)
關(guān)于android性能,內(nèi)存優(yōu)化(http://www.cnblogs.com/zyw-205520/archive/2013/02/17/2914190.html)

Android研究院之應(yīng)用開發(fā)線程池的經(jīng)典使用(http://www./archives/2439)


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲视频偷拍福利来袭| 女人精品内射国产99| 日本精品中文字幕在线视频| 精品欧美日韩一二三区| 国产熟女一区二区三区四区| 欧美一区二区不卡专区| 国内外免费在线激情视频| 区一区二区三中文字幕| 久久精品少妇内射毛片| 国产一区国产二区在线视频| 亚洲中文字幕高清视频在线观看 | 午夜精品一区免费视频| 国产一区二区三区丝袜不卡 | 欧美成人精品一区二区久久| 色婷婷视频免费在线观看| 亚洲专区一区中文字幕| 大香蕉久草网一区二区三区 | 国产传媒欧美日韩成人精品| 日本在线高清精品人妻| 精品国产亚洲av久一区二区三区| 亚洲最新中文字幕在线视频| 插进她的身体里在线观看骚| 草草视频福利在线观看| 国产精品午夜一区二区三区| 天堂网中文字幕在线视频| 99久久精品午夜一区二| 午夜福利激情性生活免费视频| 亚洲一区二区三区在线免费| 中文字幕免费观看亚洲视频 | 亚洲av在线视频一区| 中文字幕在线五月婷婷| 久久精品国产99精品亚洲| 欧美日韩国产精品第五页| 久久本道综合色狠狠五月| 富婆又大又白又丰满又紧又硬| 欧洲一级片一区二区三区| 亚洲高清亚洲欧美一区二区| 五月婷婷缴情七月丁香| 清纯少妇被捅到高潮免费观看| 人体偷拍一区二区三区| 国产午夜福利不卡片在线观看|