編輯:關於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);
@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:
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
寫在前面的話 本篇blog實現了GridView的拖拽功能。方法和上一篇自定義ListView實現拖拽ListItem項交換位置一個原理。只是在交換位置上記錄了X軸的相關
為了避免看視頻時影響到他人休息,很多用戶會考慮購買無線耳機遠程接收PC的音頻信號。問題是,有多少人會為這種小概率事件去購買無線耳機?如果你身邊有台Andro
修改文件路徑 android4.4\packages\apps\Browser\src\com\android\browser\BrowserSettings.java
這個控件之前就大致又看到V1版本的,然後坐著又做了更新,又寫了分析的博文,那這邊就簡單的把內容貼出來介紹給大家就好了(又幫我省事了)先來看下運行效果:內容都是手繪,可見原