① 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
減小對象的內存佔用
內存對象的重復利用
避免對象的內存泄露
內存使用策略優化
設計風格很大程度上會影響到程序的內存與性能,相對來說,如果大量使用類似Material Design的風格,不僅安裝包可以變小,還可以減少內存的佔用,渲染性能與載入性能都會有一定的提升。
內存優化並不就是說程序佔用的內存越少就越好,如果因為想要保持更低的內存佔用,而頻繁觸發執行gc操作,在某種程度上反而會導致應用性能整體有所下降,這里需要綜合考慮做一定的權衡。
Android的內存優化涉及的知識面還有很多:內存管理的細節,垃圾回收的工作原理,如何查找內存泄漏等等都可以展開講很多。OOM是內存優化當中比較突出的一點,盡量減少OOM的概率對內存優化有著很大的意義。
⑨ 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日)