タイトルのとおり、レイアウトの読み込み時にメモリ不足例外が発生しています。これはメモリリークの問題だと思うかもしれませんが、2日間それと戦った後、私はもうこれ以上確かではありません。アプリには10以上のアクティビティがあり、そのほとんどに背景イメージがあります。ビットマップを作成するOutOfMemoryError
これまでのところ問題は唯一のAndroid 4.0.3を実行しているギャラクシーネクサスに表示されます:私が作った
いくつかの事実/発見。 Nexus S(4.1.1)とGalaxy S II(2.3.3)で再現できませんでした。
画面の向きは変わりません。実際、私の活動のほとんどはとにかく肖像画にロックされていました。
ただ笑いのために私は
finish()
への呼び出しを追加しました。新しいアクティビティを開くときに、その時点で1つ以上のアクティビティがメモリに存在しません。onDestroy
が呼び出されていることを確認しました。cleanupDrawables()
がある@Override public void onDestroy() { super.onDestroy(); cleanupDrawables(contentView); // null all the fields referencing views and drawables System.gc(); }
:
Eclipseのヒープインスペクタを見て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)); } }
いくつかの活動がより多くのメモリを取る。すなわち、メモリは、安定したように見えるように定義
閉鎖時に解放され、時間の経過とともに安定しているように見えます。
SO画像の関連回答によれば、thisはAndroid 3以降のヒープ上にあるべきだと主張しているので、実際には画像メモリリークの場合はメモリが増えるはずです。
私の努力の最終結果は、私が以前にしたほど速くはないものの、まだメモリエラーから抜け出すことです。エラーが発生する前に私はcleanupDrawables()
コードを追加する前にビットマップの破損が見えるようになりました。私は、Bitmap.recycle()
への呼び出しが、このコードがonDestroy
でのみ呼び出されているにもかかわらず、破損の原因であると推測しました。破損は、多くのアクティビティに表示される共通スタイルの一部であるビットマップと、1つのアクティビティにのみ表示されるビットマップの両方に表示されます。
私の調査の短い結果では、むしろ決定的ではありません。この時点で、私は他に何を試していいのかわかりません。
参照のエラースタックトレース:
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