正如標題所說,我有加載佈局拋出的內存不足異常。有人會認爲這是一個內存泄漏問題,但經過兩天的爭鬥後,我不再確定了。該應用程序有10多項活動,其中大部分都有背景圖片。OutOfMemoryError創建位圖
幾個事實/發現我做:
到目前爲止,問題只在Galaxy Nexus的出現運行Android 4.0.3。我無法在Nexus S(4.1.1)和Galaxy S II(2.3.3)上重現它。
屏幕方向不會改變。事實上,我的大部分活動無論如何都鎖定在肖像上。
只是爲了笑我在打開新的活動時添加了對
finish()
的呼叫,所以當時內存中不會有多於一個的活動。驗證了onDestroy
正在被調用。
定義爲:
@Override
public void onDestroy()
{
super.onDestroy();
cleanupDrawables(contentView);
// null all the fields referencing views and drawables
System.gc();
}
其中cleanupDrawables()
是:
protected static void cleanupDrawables(View view)
{
cleanupDrawable(view.getBackground());
if (view instanceof ImageView)
cleanupDrawable(((ImageView)view).getDrawable());
else if (view instanceof TextView)
{
TextView tv = (TextView)view;
Drawable[] compounds = tv.getCompoundDrawables();
for (int i = 0; i < compounds.length; i++)
cleanupDrawable(compounds[i]);
}
else if (view instanceof ViewGroup && !(view instanceof AdapterView))
{
ViewGroup vg = (ViewGroup)view;
for (int i = 0; i < vg.getChildCount(); i++)
cleanupDrawables(vg.getChildAt(i));
vg.removeAllViews();
}
}
protected static void cleanupDrawable(Drawable d)
{
if (d == null)
return;
d.setCallback(null);
if (d instanceof BitmapDrawable)
((BitmapDrawable)d).getBitmap().recycle();
else if (d instanceof LayerDrawable)
{
LayerDrawable layers = (LayerDrawable)d;
for (int i = 0; i < layers.getNumberOfLayers(); i++)
cleanupDrawable(layers.getDrawable(i));
}
}
看着Eclipse的堆檢查,內存似乎是穩定的,即一些活動需要更多的內存比其他人多,但是它在關閉時被釋放,並且隨着時間的推移它看起來很穩定。
根據SO圖像上的相關答案存儲在本機內存中,但是this老兄聲稱他們應該在Android 3以後堆上,所以如果這確實是圖像內存泄漏,我應該看到內存增加。
我努力的最終結果是,我仍然發現內存不足錯誤,但速度不如以前那麼快。在發生錯誤之前,我開始看到可見的位圖損壞,在添加cleanupDrawables()
代碼之前,情況並非如此。我推斷,致電Bitmap.recycle()
正在導致腐敗,儘管此代碼僅在onDestroy
上被調用。兩個位圖都出現損壞,這些位圖都是出現在許多活動中的常見樣式的一部分,以及僅在一個活動中顯示的位圖。
在我調查的結果短是相當不確定的。在這一點上,我不知道還有什麼要嘗試。
參考錯誤堆棧跟蹤:
08-22 10:49:51.889: E/AndroidRuntime(31697): java.lang.RuntimeException: Unable to start activity ComponentInfo{klick.beatbleeds/klick.beatbleeds.Bleeds}: android.view.InflateException: Binary XML file line #67: Error inflating class <unknown>
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.access$600(ActivityThread.java:122)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.os.Handler.dispatchMessage(Handler.java:99)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.os.Looper.loop(Looper.java:137)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.main(ActivityThread.java:4340)
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Method.invokeNative(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Method.invoke(Method.java:511)
08-22 10:49:51.889: E/AndroidRuntime(31697): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-22 10:49:51.889: E/AndroidRuntime(31697): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-22 10:49:51.889: E/AndroidRuntime(31697): at dalvik.system.NativeStart.main(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): Caused by: android.view.InflateException: Binary XML file line #67: Error inflating class <unknown>
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.createView(LayoutInflater.java:606)
08-22 10:49:51.889: E/AndroidRuntime(31697): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
08-22 10:49:51.889: E/AndroidRuntime(31697): at klick.beatbleeds.ActivityBase.setContentView(ActivityBase.java:82)
08-22 10:49:51.889: E/AndroidRuntime(31697): at klick.beatbleeds.Bleeds.onCreate(Bleeds.java:40)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.Activity.performCreate(Activity.java:4465)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
08-22 10:49:51.889: E/AndroidRuntime(31697): ... 11 more
08-22 10:49:51.889: E/AndroidRuntime(31697): Caused by: java.lang.reflect.InvocationTargetException
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Constructor.constructNative(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.createView(LayoutInflater.java:586)
08-22 10:49:51.889: E/AndroidRuntime(31697): ... 23 more
08-22 10:49:51.889: E/AndroidRuntime(31697): Caused by: java.lang.OutOfMemoryError
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.nativeCreate(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:524)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.content.res.Resources.loadDrawable(Resources.java:1937)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.View.<init>(View.java:2780)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.ViewGroup.<init>(ViewGroup.java:385)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.widget.LinearLayout.<init>(LinearLayout.java:174)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.widget.LinearLayout.<init>(LinearLayout.java:170)
08-22 10:49:51.889: E/AndroidRuntime(31697): ... 26 more
這裏是一個視圖的截圖來了解有多少圖像用在這裏
那麼,這些位圖(分辨率)有多大?如果您用較小的圖像替換它們(僅用於踢腿),問題會消失嗎? – dmon
從視圖中清理位圖資源不是必需的,只會減慢您轉換到新活動的速度。你膨脹什麼樣的佈局以及多少圖像? – DeeV
我也同意@Deev,你不需要手動「清理」你的位圖摧毀。 – dmon