導航:首頁 > 操作系統 > 如何避免oomAndroid

如何避免oomAndroid

發布時間:2022-11-27 16:35:58

android中怎麼防止oom

內存泄露的原因:
1. Handler造成內存泄漏

private Handler handler = new Handler(){
@Override
public void handMessage(Message msg){

}
}
當使用內部類(包括匿名類)來創建Handler時,Handler對象會隱式地持有一個外部類對象(通常是一個Activity)的引用。
而Handler通常會伴隨一個耗時的後台線程(例如訪問網路或者從網路上拉取圖片)一起出現,這個後台線程在任務執行完畢(例如圖片下載完成)之後,通過消息機制通知Handler,然後Handler把圖片更新到界面上(主線程中)。
當用戶在網路請求過程中關閉了Activity,正常情況下,Activity不再被使用,它就有可能在GC檢查時被回收掉。但是由於這時線程尚未執行完,而該線程持有Handler的引用,Handler持有Activity的引用,就導致Activity無法被回收(即內存泄露),直到網路請求結束(例如圖片下載完成)。
另外,如果你執行了Handler的postDelayed()方法,該方法會將你的Handler裝入一個Message,並把這條Message推到MessageQueue中,那麼在你設定的delay到達之前,會有一條MessageQueue —> Message —> Handler —> Activity的鏈,導致你的Activity被持有引用而無法被回收。
使用Handler導致內存泄露的解決辦法:
一、通過程序邏輯進行保護
A. 在finish Activity的時候停掉你的後台線程,線程停掉了,就相當於切斷了Handler與外部連接的線,Activity自然會在合適的時候被回收。
B. 如果Handler被delay的Message持有了引用,那麼使用相應的Handler的removeCallbacks()方法,把消息對象從消息隊列中移除即可。
二、將Handler聲明為靜態類
靜態類不持有外部類的引用對象,所以Activity可以隨意被回收。
static class MyHandler extends Handler{

@Override
public void handleMessage(Message msg){
}
}
此時由於Handler不再持有外部類對象的引用,導致程序不允許你在Handler中操作Activity中的對象。所以你需要在Handler中增加一個對Activity的弱引用(WeakReference)
static class MyHandler extends Handler{
WeakReference<Activity> activityReference;
public MyHandler(Activity activity){
activityReference = new WeakReference<Activity>(activity);
}

@Override
public void handleMessage(Message msg){
final Activity activity = activityReference.get();
}
}
對應以上的代碼,用戶在關閉Activity之後,就算後台線程還沒結束,但由於僅有一條來自Handler的弱引用指向Activity,所以GC仍然會在檢查的時候把Activity回收掉。
So, 關於Handler內存泄露的問題就不會出現。

② android何時會發生oom怎麼解決oom

首先,OOM就是內存溢出,即Out Of Memory。也就是說內存佔有量超過了VM所分配的最大。
怎麼解決OOM,通常OOM都發生在需要用到大量內存的情況下(創建或解析Bitmap,分配特大的數組等),在這樣的一種情況下,就可能出現OOM,據我現在了解到,多數OOM都是因為Bitmap太大。所以,這里我就專門針對如何解決Bitmap的OOM。其實最核發的就是只載入可見范圍內的Bitmap,試想這樣一種情況,在GridView或ListView中,數據量有5000,每一屏只顯示20個元素,那麼不可見的,我們是不需要保存Bitmap在內在中的。所以我們就是只把那麼可見的Bitmap保留在內存中,那些不可見的,就釋放掉。當元素滑出來時,再去載入Bitmap。
這里我有兩種方式,都可以避免OOM。

③ oom如何解決和預防

盡量提高自己的免疫力,然後不斷的鍛煉身體,這樣的話對於預防來說是有很好的療效。
但是我們還需要掌握一定的方式方法。

④ 怎麼解決oom android

如果是第一次創建的時候就出錯,那試試在創建bitmap的時候不要把public static Bitmap createBitmap (int width, int height, Bitmap.Config config)的第三個參數寫成ARGB_8888,換成其他的值。

如果是多次創建的時候才OOM,那麼一定要想辦法,在合適的地方,對你已經創建的bitmap進行recycle操作。

⑤ android使用全局的dialogview怎樣避免oom

避免OOM的第一步就是要盡量減少新分配出來的對象佔用內存的大小,盡量使用更加輕量的對象。
1)使用更加輕量的數據結構
1、考慮使用ArrayMap/SparseArray(SparseBoolMap,SparseIntMap,SparseLongMap,LongSparseMap)而不是HashMap等傳統數據結構
ArrayMap、SparseArray使用場景:
對象個數的數量級最好是千以內
數據組織形式包含Map結構

⑥ android oom問題 如何避免

ROM有什麼問題,你是否能說一下,如果你說的是有些人不斷地刷ROM,那不過是他們的興趣罷了,沒有最好的ROM,而那些刷機不斷地人則是在找更好的ROM,你如果覺得你的ROM可以忍受,你就不用刷,如果你想試一試新的系統,你就可以刷一下不同的ROM,其實ROM對手機的性能影響還是挺大的,一個好的ROM可以使你的手機更省電,CPU主頻更高,你要不要刷,自己看著辦把。
說了這么多,我都覺得自己說的挺亂的,如果你有什麼問題,接著問吧

⑦ android圖片壓縮避免OOM

簡單吹下牛:很多app都會要載入圖片,但是如果不壓縮圖片就很容易OOM,

個人看來OOM 出現原因總的來說分為兩種:

一種是內存溢出(好像在扯淡,OOM本身就是內存溢出)

另一種是:圖片過大,一個屏幕顯示不完全造成,似乎也是一。。 如有錯誤純屬扯淡;

為了避免上面的情況:載入圖片的時候可以進行壓縮,上傳的時候要可以進行壓縮,在圖片不可見的時候進行回收(onDetach()),再吹一句 用了fresco+壓縮之後載入圖片完全沒問題了。

一、質量壓縮方法:

privateBitmap compressImage(Bitmap image) {

ByteArrayOutputStream baos =newByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,100, baos);//質量壓縮方法,這里100表示不壓縮,把壓縮後的數據存放到baos中

intoptions =100;

while( baos.toByteArray().length /1024>100) {//循環判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮

baos.reset();//重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG, options, baos);//這里壓縮options%,把壓縮後的數據存放到baos中

options -=10;//每次都減少10

}

ByteArrayInputStream isBm =newByteArrayInputStream(baos.toByteArray());//把壓縮後的數據baos存放到ByteArrayInputStream中

Bitmap bitmap = BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream數據生成圖片

returnbitmap;

}

二、圖片按比例大小壓縮方法(根據Bitmap圖片壓縮)

privateBitmap comp(Bitmap image) {

ByteArrayOutputStream baos =newByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,100, baos);

if( baos.toByteArray().length /1024>1024) {//判斷如果圖片大於1M,進行壓縮避免在生成圖片(BitmapFactory.decodeStream)時溢出

baos.reset();//重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG,50, baos);//這里壓縮50%,把壓縮後的數據存放到baos中

}

ByteArrayInputStream isBm =newByteArrayInputStream(baos.toByteArray());

BitmapFactory.Options newOpts =newBitmapFactory.Options();

//開始讀入圖片,此時把options.inJustDecodeBounds 設回true了

newOpts.inJustDecodeBounds =true;

Bitmap bitmap = BitmapFactory.decodeStream(isBm,null, newOpts);

newOpts.inJustDecodeBounds =false;

intw = newOpts.outWidth;

inth = newOpts.outHeight;

//現在主流手機比較多是800*480解析度,所以高和寬我們設置為

floathh = 800f;//這里設置高度為800f

floatww = 480f;//這里設置寬度為480f

//縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可

intbe =1;//be=1表示不縮放

if(w > h && w > ww) {//如果寬度大的話根據寬度固定大小縮放

be = (int) (newOpts.outWidth / ww);

}elseif(w < h && h > hh) {//如果高度高的話根據寬度固定大小縮放

be = (int) (newOpts.outHeight / hh);

}

if(be <=0)

be =1;

newOpts.inSampleSize = be;//設置縮放比例

//重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了

isBm =newByteArrayInputStream(baos.toByteArray());

bitmap = BitmapFactory.decodeStream(isBm,null, newOpts);

returncompressImage(bitmap);//壓縮好比例大小後再進行質量壓縮

}

⑧ android開發內存優化之如何有效避免oom

  1. 減小對象的內存佔用

  2. 內存對象的重復利用

  3. 避免對象的內存泄露

  4. 內存使用策略優化

⑨ Android Bitmap 內存以及OOM問題討論

都知道在Android中, 每個應用所使用的內存是有限的,現在的手機通常最大的內存使用為256M, 目前還沒發現Android中一個應用的最大內存分配超過256M的(經測試華為手機的最大內存是385M)

相關API:

ActivityManager.getMemoryClass(),首先獲取系統服務中的ActivityManager

如下:

(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

可以獲取到相關信息

最近一直被項目的OOM問題困擾, 在網上查閱相關資料,前前後後讀了不下於30篇,這些篇幅講解的東西都是千篇一律,並沒有解決到實際問題

也在慕課網學習了內存優化章節

這是慕課網講師的PPT,我截屏的

這里來仔細分析一下:

第一個,  注意臨時Bitmap對象的及時回收, 來看下相關API

直接上圖

經過我無數次的使用Android studio工具自帶的MAT分析工具後, 得出一個很嚴謹的結論, 此方法並不奏效...

Android中Bitmap的內存存放在堆區, Google 的Bitmap的recycle方法注釋也可以了解到

Android歷史版本不是很清楚, 據說Android3.0之前Bitmap是存放在native區域,可以進行手動釋放,然而3.0之後Bitmap是存放在Java層的堆區,沒錯是heap, 內存管理直接交由系統GC管理,你還這樣釋放資源有意義?無非是給自己的一點心理安慰罷了, 告訴你沒卵用

又有人在說要釋放內存使用System.gc() ???  對就是主動觸發垃圾回收,這個API是開發者自行調用的嗎?那麼系統管理內存還有什麼意義?這不是誤人子弟嗎,這個API不能調用的, 因為沒卵用的, 具體自己參照MAT工具自行分析.即便垃圾回收真的被觸發了, 所有線程停滯由系統來清理垃圾, 造成的後果是嚴重卡頓!!!

再看一個API:

我在網上苦苦追尋內存過高的問題後,發現了這個API,經過無數次實踐後我得出一個結論,沒卵用...開發者可以拋棄它

綜上所訴, 第一點講解的內存優化問題可以直接PASS掉, 無非給自己一點心理安慰: 我已經處理好了內存問題, 程序不會OOM?

第二點. 避免Bitmap的浪費

直接說結論, 這個是非常行之有效的,並且是一定能解決問題的

具體怎麼操作呢? 自己實現LruCache這個類, 就是這么弄, 原理就是解碼復用, 在內存中已經解碼好的Bitmap直接拿出來使用, 沒有的在載入到內存進行解析, 這個非常有效,但是並不能讓你避免OOM

第三點, try-catch某些大內存分配的操作

這點上,我又要開始疑問了, 我Java功底不是很好

Java中發生內存溢出時,拋出的是OutOfMemoryError, 它的父類是VirtualMachineError

這玩意能catch住? 它屬於Error范疇, 你能捕獲?請Java大神出來說一下,我解釋不清楚

第四點, 載入Bitmap 縮放比例, 解碼格式, 局部載入

先來分析一下縮放比例:

按照市面上主流的手機解析度來分析現在Android主流的解析度是1920X1080, 如果一個ImageView控制項剛好就是屏幕全屏,怎麼說?直接佔用掉8M內存, 想想一個實際的需求情況

一個查看大圖的頁面, 不斷的關閉,打開查看新的大圖,問題就來了,內存一直在暴增,遲早會突破界限OOM掉

解析度是2K屏呢? 更恐怖了, 隨著手機設備的屏幕解析度提升, 載入圖像需要的內存也是倍增的, 因為應用的最大內存並沒有增加

結論: 縮放比例可以有效的降低內存佔用問題, 但不是絕對的救命稻草, 該縮放的還是要縮放,而且必須縮放,就是采樣  現在通常都是圖片載入框架來完成,類似Glide.Picasso,Fresco等,他們可以幫助你減少工作量, 內存問題還是存在

再來分析一下解碼格式:

這個跟縮放比例效果差不多, 只是同樣的解析度的圖片載入到內存中時佔用內存減少了

比如ARGB_8888 共32位

RGB_565  共16位

ARGB_4444 共16位

很明顯這樣格式圖片載入的內存情況是ARGB_8888是其他格式的兩倍內存

另外的問題是ARGB_8888看起來很清晰的, 其它的看起來圖片有種糊了的感覺,自己選擇吧

結論, 降低內存佔用非常有效

最後一個是局部載入, 並沒有怎麼使用到,也不清楚就不說了

最後還有一個方法避免OOM, 開啟largeHeap屬性, 但是但是, 以前我們開啟這個屬性後被Oppo應用市場認定為佔用內存過高, 不建議用戶安裝......所以我們又取消了!

總的來說, Bitmap在內存是變現的是不可控, 我項目OOM問題一直沒有得到有效解決,因為圖片編輯視頻編輯之類的功能佔用內存過高,繼續使用OOM是必然的, 跟IOS的同學交流了一番,他們說IOS的應用內存可以佔用到1個G以上, 輕松跑到500M是沒問題的, IOS的內存機制可以持續給內存使用, 具體我也不清楚,並且他們可以手動釋放內存?malloc, free這樣子?

如果大家有比較好的方案,還望留言交流互相幫助 [笑臉.gif]

補充: Android8.0開始Bitmap數據內存存在native層, 單個應用可用的內存顯著增長, 極大的降低了OOM的概率(2018年3月22日)

閱讀全文

與如何避免oomAndroid相關的資料

熱點內容
加密貨幣買什麼比較靠譜 瀏覽:277
用圖片的地圖再編譯的地方 瀏覽:462
python監控系統進程 瀏覽:236
群暉怎麼取消照片共享文件夾 瀏覽:156
程序員那麼可愛第幾集陸璃懷孕 瀏覽:615
西門子st編程手冊 瀏覽:59
mt4編程書籍 瀏覽:21
單片機模擬實驗設置電壓 瀏覽:948
如何用電腦打開安卓手機內存 瀏覽:860
java數據訪問層 瀏覽:181
代碼優化是編譯程序的必要階段 瀏覽:623
程序員那麼可愛孩子還在嗎 瀏覽:513
以下哪些是資料庫編程技術 瀏覽:164
水冷壓縮冷凝機組 瀏覽:177
小米路由器app怎麼加黑名單 瀏覽:433
證券交易2012pdf 瀏覽:208
單線程和多線程編譯 瀏覽:155
游戲被加密了刪不了怎麼辦 瀏覽:475
二建6米的柱子加密多少箍筋 瀏覽:648
怎麼簡單易懂的了解伺服器 瀏覽:356