Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 細節之android.view.InflateException: Binary XML file line #95: Error inflating class(out of m)

android 細節之android.view.InflateException: Binary XML file line #95: Error inflating class(out of m)

編輯:關於Android編程

今天的異常很有意思,叫做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中同樣配置了如下代碼:

@Override
	protected 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:

  1. Make sure you are not leak activity context.

  2. 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);
  3. Recycle bitmaps if you don't need them anymore.

  4. If you use memory cache, like memory-lru, make sure it is not using to much memory.

  5. 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.

  6. 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

  7. 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.

  8. 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.

  9. 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


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved