最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決Android平臺(tái)中應(yīng)用程序OOM異常的方法

 更新時(shí)間:2015年12月14日 16:22:45   作者:leehong2005  
這篇文章主要介紹了解決Android平臺(tái)中應(yīng)用程序OOM異常的方法,通常這一塊也是程序中的重點(diǎn)之一,感興趣的小伙伴們可以參考一下

在Android平臺(tái)上面,應(yīng)用程序OOM異常永遠(yuǎn)都是值得關(guān)注的問題。通常這一塊也是程序這中的重點(diǎn)之一。這下我就如何解決OOM作一點(diǎn)簡(jiǎn)單的介紹。

首先,OOM就是內(nèi)存溢出,即Out Of Memory。也就是說內(nèi)存占有量超過了VM所分配的最大。

怎么解決OOM,通常OOM都發(fā)生在需要用到大量?jī)?nèi)存的情況下(創(chuàng)建或解析Bitmap,分配特大的數(shù)組等),在這樣的一種情況下,就可能出現(xiàn)OOM,據(jù)我現(xiàn)在了解到,多數(shù)OOM都是因?yàn)锽itmap太大。所以,這里我就專門針對(duì)如何解決Bitmap的OOM。其實(shí)最核發(fā)的就是只加載可見范圍內(nèi)的Bitmap,試想這樣一種情況,在GridView或ListView中,數(shù)據(jù)量有5000,每一屏只顯示20個(gè)元素,那么不可見的,我們是不需要保存Bitmap在內(nèi)在中的。所以我們就是只把那么可見的Bitmap保留在內(nèi)存中,那些不可見的,就釋放掉。當(dāng)元素滑出來時(shí),再去加載Bitmap。

這里我有兩種方式,都可以避免OOM。

一、主動(dòng)釋放Bitmap的內(nèi)存
這種方式我簡(jiǎn)單說一下,不太推薦,這也是我最開始使用的一種方法,但最后證明它不是最好的。(不推薦)

它的本質(zhì)思路是:
  1、只加載可見區(qū)域的Bitmap

  2、滑動(dòng)時(shí)不加載

  3、停止滑動(dòng)(Idle)后,開始重新加載可見區(qū)域的圖片

  4、釋放滑出可見區(qū)域的Bitmap的內(nèi)在。

它比較復(fù)雜:
    1、我們需要監(jiān)聽GridView/ListView的滑動(dòng)事件,這個(gè)很簡(jiǎn)單做到,AbsListView#setOnScrollListener(OnScrollListener l)

    2、主動(dòng)調(diào)用Bitmap#recycle()方法,它會(huì)導(dǎo)致一個(gè)問題,必須判斷這個(gè)Bitmap是否被一個(gè)View(ImageView等)所引用,如果被引用,我們不能簡(jiǎn)單地調(diào)用recycle()方法,這樣會(huì)導(dǎo)致異常,說是View使用了一個(gè)已經(jīng)被回收的Bitmap。

    3,我們必須設(shè)計(jì)自己的線程來控制開始/暫停等,因?yàn)镚ridView/ListView的滑動(dòng)狀態(tài)可能不斷地變化,也就是說滑動(dòng)->停止->滑動(dòng),這種狀態(tài)可能不斷變化,這樣就會(huì)導(dǎo)致我們的線程中的run()方法里面的邏輯比較復(fù)雜,一旦復(fù)雜,問題就可能就得更多。

基于以上幾點(diǎn),這種方式不是最好的,所以不推薦。

二、設(shè)計(jì)Cache
    這種方式,我覺得是比較好的一種,它首先利用了cache,我認(rèn)為cache是一個(gè)很重要的東西,把Bitmap的內(nèi)存單獨(dú)放在一個(gè)地方來管理,這個(gè)地方就是cache,它的容量是一定的,我們可能會(huì)不斷的向這個(gè)cache中添加元素,也可能不斷的移除元素。

為了更好的說明這種方式,先要介紹一下LruCache。

LruCache
    1、這其實(shí)就是一個(gè)LinkedHashMap,任意時(shí)刻,當(dāng)一個(gè)值被訪問時(shí),它就會(huì)被移動(dòng)到隊(duì)列的開始位置,所以這也是為什么要用LinkedHashMap的原因,因?yàn)橐l繁的做移動(dòng)操作,為了提高性能,所以要用LinkedHashMap。當(dāng)cache滿了時(shí),此時(shí)再向cache里面添加一個(gè)值,那么,在隊(duì)列最后的值就會(huì)從隊(duì)列里面移除,這個(gè)值就有可能被GC回收掉。

    2、如果我們想主動(dòng)釋放內(nèi)存,也是可以的,我們可以重寫entryRemoved(Boolean, K, V, V)方法。

    3、這個(gè)類是線程安全的,在多線程下面使用這個(gè)類,沒不會(huì)存在問題。

synchronized (cache) { 
   if (cache.get(key) == null) { 
     cache.put(key, value); 
  }} 

    4、LruCache的APILevel是12,也就是說,我們?cè)赟DK 2.3.x以下是無法使用的,但是沒關(guān)系,LruCache的源碼不算復(fù)雜,我們可以直接把它拷貝到自己的工程目錄就可以了。
 AsyncTask<>
    這個(gè)類也是一個(gè)很重要也很常用的類。它封裝了Thread和Handler,我們使用就更加方便,不用關(guān)注Handler,我們知道,在后臺(tái)線程中是不能更新UI,而很多情況下,我們?cè)诤笈_(tái)線程做完一件事情后,一般都會(huì)更新UI,一般的做法是向關(guān)聯(lián)到UI線程的Handler發(fā)送一個(gè)message,在Handler里面去處理這個(gè)message,從而更新UI。用了AsyncTask之后,我們就不用關(guān)注Handler了。這個(gè)類有幾個(gè)重要的方法:

    1)、onPreExecute(): 在UI線程里面調(diào)用,它在這個(gè)task執(zhí)行后會(huì)立即調(diào)用。我們?cè)谶@個(gè)方法里面通常是用于建立一個(gè)任務(wù),比如顯示一個(gè)等待對(duì)話框來通知用戶。

    2)、doInBackground(Params...):這個(gè)方法從名字就可以看出,它是運(yùn)行在后臺(tái)線程的,在這個(gè)方法里面,去做耗時(shí)的事情,比如下載訪問網(wǎng)絡(luò),操作文件等。這這個(gè)方法里面,我們可以調(diào)用publishProgress(Progress...)來調(diào)用當(dāng)前任務(wù)的進(jìn)度,調(diào)用了這個(gè)方法后,對(duì)應(yīng)的onProgressUpdate(Progress...)方法會(huì)被調(diào)用,這個(gè)方法是運(yùn)行在UI線程的。

    3)、onProgressUpdate(Progress...):運(yùn)行在UI線程,在調(diào)用publishProgress()方法之后。這個(gè)方法用來在UI上顯示任何形式的進(jìn)度,比如你可以顯示一個(gè)等待對(duì)話框,也可以顯示一個(gè)文本形式的log,還可以顯示toast對(duì)話框。

    4)、onPostExecute(Result):當(dāng)task結(jié)束后調(diào)用,它運(yùn)行在UI線程。

    5)、取消一個(gè)task,我們可以在任何時(shí)候調(diào)用cancel(Boolean)來取消一個(gè)任務(wù),當(dāng)調(diào)用了cancel()方法后,onCancelled(Object)方法就會(huì)被調(diào)用,onPostExecute(Object)方法不會(huì)被調(diào)用,在doInBackground(Object[])方法中,我們可以用isCancelled()方法來檢查任務(wù)是否取消。

    6)、幾點(diǎn)規(guī)則

AsyncTask實(shí)例必須在UI線程中創(chuàng)建  
execute(Params...)方法必須在UI線程中調(diào)用。
不用手動(dòng)調(diào)用onPreExecute(), onPostExecute(), doInBackground(), onProgressUpdate()方法。
一個(gè)任務(wù)只能被執(zhí)行一次。 
總的思路
    1、始終從cache中去取Bitmap,如果取到Bitmap,就直接把這個(gè)Bitmap設(shè)置到ImageView上面。

    2、如果緩存中不存在,那么啟動(dòng)一個(gè)task去加載(可能從文件來,也可能從網(wǎng)絡(luò))。

    3、每一個(gè)ImageView上面都可能綁定一個(gè)task,所以,這個(gè)ImageView必須提供一個(gè)方法能得到與之相關(guān)聯(lián)的task,為什么要這樣做?因?yàn)樵诮o一個(gè)ImageView綁定task之前,必須要把原先的task取消。

以上就是解決應(yīng)用程序OOM異常的方法,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

最新評(píng)論

横峰县| 鹿泉市| 全南县| 无锡市| 永福县| 嘉黎县| 武山县| 温宿县| 黄梅县| 辛集市| 夹江县| 芒康县| 青州市| 景泰县| 克东县| 开封市| 封开县| 木里| 都匀市| 九龙城区| 怀宁县| 鱼台县| 项城市| 遵义县| 包头市| 邯郸市| 广灵县| 建昌县| 黄骅市| 金乡县| 泰兴市| 河北省| 惠来县| 台南市| 蓝山县| 鹤峰县| 扬中市| 米泉市| 波密县| 苏尼特右旗| 东宁县|