android 細節之android.view.InflateException: Binary XML file line #95: Error inflating class(out of m),
今天的異常很有意思,叫做android.view.InflateException: Binary XML file line #95: Error inflating class(out of memory) 。
其實是因為out of memory,導致 xml是不可能被充氣成功,因此activity的onCreate方法中,
setContentView(R.layout.***)也就不可能成功調用.
他出現在我有多個教學動畫,並且播放的動畫,是基於imageView,imageView的背景是我們項目的大型圖片。
出錯情境為:開啟一個activity,這個activity只用來播放一個動畫。然後手動back,關掉activity(finish)。開第二的activity,第二個activity綁定的layout和第一個不一樣,播放另一個動畫。手動back,關掉activity。
以此類推,多次運行後會出現做android.view.InflateException: Binary XML file line #95: Error inflating class.
caused by out of memory.
一開始我怎麼也沒有想明白,每次我的activity都finish了,怎麼可能會記憶體不足。
於是上網找答案,在親愛的stackoverflow上發現了大神的評論,(大神請移步:http://stackoverflow.com/questions/7536988/android-app-out-of-memory-issues-tried-everything-and-still-at-a-loss/7576275),原來提出問題的哥也試了everything,哈哈。
其實是因為我們並沒有手工回收資源,換句話說,java的記憶體回收機制並沒有那麼的聰明,我們finish掉了,但裡面相關的資源他未必回收。有可能他自以為很聰明的留下來等著我們下次使用。所以我們需要在onStop的方法中手動釋放imageView這樣的大型資源。
大神的寫法如下:
Drawable d = imageView.getDrawable(); if (d != null) d.setCallback(null); imageView.setImageDrawable(null); imageView.setBackgroundDrawable(null);
我之後在我們項目中的五個播放動畫的教學activity中同樣配置了如下代碼:
@Overrideprotected void onStop() {releaseImageViews();super.onStop();}private void releaseImageViews() {releaseImageView(mTerminal);releaseImageView(mFingerPressInnerRing);releaseImageView(mFingerPressMiddleRing);releaseImageView(mFingerPressOuterRing);releaseImageView(mInnerRing);releaseImageView(mMiddleRing);releaseImageView(mOuterRing);releaseImageView(mPhone);releaseImageView(mScreen);}private void releaseImageView(ImageView imageView) {Drawable d = imageView.getDrawable();if (d != null)d.setCallback(null);imageView.setImageDrawable(null);imageView.setBackgroundDrawable(null);}
此問題便解決了。
異常很經典,特記錄之。
大神的tips:
Some tips:
Make sure you are not leak activity context.
Make sure you are don't keep references on bitmaps. Clean all of your ImageView's in Activity#onStop, something like this:
Drawable d = imageView.getDrawable(); if (d != null) d.setCallback(null); imageView.setImageDrawable(null); imageView.setBackgroundDrawable(null);
Recycle bitmaps if you don't need them anymore.
If you use memory cache, like memory-lru, make sure it is not using to much memory.
Not only images take alot of memory, make sure you don't keep too much other data in memory. This easily can happens if you have infinite lists in your app. Try to cache data in DataBase.
On android 4.2, there is a bug(stackoverflow#13754876) with hardware acceleration, so if you use hardwareAccelerated=true in your manifest it will leak memory. GLES20DisplayList - keep holding references, even if you did step (2) and no one else is referencing to this bitmap. Here you need:
a) disable hardware acceleration for api 16/17;
or
b) detach view that holding bitmap
For Android 3+ you can try to use android:largeHeap="true" in your AndroidManifest. But it will not solve your memory problems, just postpone them.
If you need, like, infinite navigation, then Fragments - should be your choice. So you will have 1 activity, which will just switch between fragments. This way you will also solve some memory issues, like number 4.
Use Memory Analyzer to find out the cause of your memory leak.
Here is very good video from Google I/O 2011: Memory management for Android Apps
If you dealing with bitmaps this should be a must read: Displaying Bitmaps Efficiently
Caused by: androidviewInflateException: Binary XML file line #2
看起來沒問題 我想應該是你的PullToRefreshView寫的有問題吧
android自訂View在xml中的使用出錯?到底該怎使用?指教
android.view.InflateException: Binary XML file line #8: Error inflating class cm.test.testview
1. 確認準確包名 “cm.test.testview” -->
2. 確認 inflate 使用
[code] 三種方式可以產生LayoutInflater:
LayoutInflaterinflater=LayoutInflater.from(this);
LayoutInflaterinflater=getLayoutInflater();
LayoutInflaterinflater=(LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
然後調用inflate方法將xml布局檔案轉成View
publicViewinflate(intresource,ViewGrouproot,booleanattachToRoot)
在View類中,也有inflate方法
publicstaticViewinflate(Contextcontext,intresource,ViewGrouproot)
[/code]