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

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

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

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

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

怎么解決OOM,通常OOM都發(fā)生在需要用到大量內(nèi)存的情況下(創(chuàng)建或解析Bitmap,分配特大的數(shù)組等),在這樣的一種情況下,就可能出現(xiàn)OOM,據(jù)我現(xiàn)在了解到,多數(shù)OOM都是因?yàn)锽itmap太大。所以,這里我就專門針對如何解決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。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    4、LruCache的APILevel是12,也就是說,我們在SDK 2.3.x以下是無法使用的,但是沒關(guān)系,LruCache的源碼不算復(fù)雜,我們可以直接把它拷貝到自己的工程目錄就可以了。
 AsyncTask<>
    這個(gè)類也是一個(gè)很重要也很常用的類。它封裝了Thread和Handler,我們使用就更加方便,不用關(guān)注Handler,我們知道,在后臺線程中是不能更新UI,而很多情況下,我們在后臺線程做完一件事情后,一般都會更新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í)行后會立即調(diào)用。我們在這個(gè)方法里面通常是用于建立一個(gè)任務(wù),比如顯示一個(gè)等待對話框來通知用戶。

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

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

    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)方法就會被調(diào)用,onPostExecute(Object)方法不會被調(diào)用,在doInBackground(Object[])方法中,我們可以用isCancelled()方法來檢查任務(wù)是否取消。

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

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

    2、如果緩存中不存在,那么啟動一個(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異常的方法,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

最新評論

沁阳市| 临猗县| 邻水| 法库县| 建水县| 青川县| 淮阳县| 泗洪县| 大城县| 志丹县| 十堰市| 额济纳旗| 武平县| 伊通| 成都市| 岳阳县| 托里县| 宜城市| 高碑店市| 盐城市| 中江县| 大埔区| 伊金霍洛旗| 鄂温| 大田县| 通山县| 屏边| 嵊州市| 韶关市| 卢湾区| 永城市| 齐齐哈尔市| 县级市| 太保市| 托克逊县| 澄江县| 从江县| 九寨沟县| 眉山市| 山东省| 民县|