24MB ヒープの WVGA800 画面を使用して API_14 エミュレーターで実行すると、ビューの背景画像に問題が発生します。ビュー ナビゲーション間でドローアブルが解放されていないように見え、3 つのビューが表示された後、ビューを膨張させるメモリ不足の例外が発生します。 .
アプリは、起動時のスプラッシュ スクリーンに使用する背景画像として 480x800 PNG を持つ SplashScreenActivity で開始します。アプリは、新しい 480x800 ピクセルも表示する次のビューに移動します。3 番目の画面のナビゲーションにも 480x800 の PNG が含まれており、これはメモリ不足エラーが発生したときのものです。まず、axmlレイアウトで背景を設定してこれを試しました。次に、SplashScreenActivity.OnCreate() メソッドと他の 2 つのビュー OnCreate() メソッドのコードから背景を設定する別の方法を試しました。これが問題である場合に備えて、ドローアブルを処分するとモノVMから解放されることを他の場所で読みました。助けになったもう 1 つのトリックは、OnCreate() の開始時に GC を強制することでした。これにより、ヒープの 12% が解放されましたが、成功は限定的でした。
public class SplashScreenActivity: MvxBaseSplashScreenActivity
{
public SplashScreenActivity() : base(Resource.Layout.SplashScreen) { }
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
using (var drawable = Resources.GetDrawable(Resource.Drawable.LoadingScreen))
Window.SetBackgroundDrawable(drawable);
}
}
そして2つ目の見方
public class GameView : MvxBindingActivityView<GameViewModel>
{
public GameView() { SoundBinding.GameView = this; }
protected override void OnViewModelSet() { SetContentView(Resource.Layout.GameView); }
protected override void OnCreate(Bundle bundle)
{
GC.Collect();
base.OnCreate(bundle);
using (var drawable = Resources.GetDrawable(Resource.Drawable.GameScreenBackground))
Window.SetBackgroundDrawable(drawable);
}
}
このすべての後、アプリケーションは、3 番目の同様のビューをバックグラウンドで膨張させると、まだメモリ不足になります。時々それはうまくいきますが、画面が循環するにつれて最終的に発生します。MAT のヒープ ダンプを見ると、サイズが 3.5M の bitmapDrawable が 2 つあることがわかります。これらは私の2つのビットマップだと思います。2 番目の BitmapDrawable では、それを保持しているビューがはっきりとわかります。メモリにはまだ別のビットマップがありますが、GC ルートへのパスがわかりません。これは、最初の SplashScreenActivity ビューで最初にロードされた PNG でなければなりません。これは、弱参照のない GC ルートへの MAT パスです。それを保持している弱い参照もあります。
android.graphics.Bitmap @ 0x4134fb08 | 40 | 3,456,056
|- mBitmap android.graphics.drawable.BitmapDrawable @ 0x4134f568 | 64 | 136
| |- mBackgroundDrawable com.android.internal.policy.impl.PhoneWindow @ 0x41356cc8 Native Stack | 200 | 1,168
| |- mBGDrawable com.android.internal.policy.impl.PhoneWindow$DecorView @ 0x41357560 Native Stack| 560 | 968
| '- Total: 2 entries | |
|- mBitmap android.graphics.drawable.BitmapDrawable$BitmapState @ 0x4134f460 | 40 | 40
| '- referent java.lang.ref.WeakReference @ 0x4134ff40 | 24 | 24
'- Total: 2 entries | |
というわけで質問タイム。次のビューがインフレートされる前に、これらのドローアブルが確実に解放されるようにするにはどうすればよいですか? ビューのレイアウトではなく、コードで背景を設定する必要がありますか? ここで見られるようにコールバックを null に設定して unbindDrawables() を unbindDrawables() にする必要がありますか? ? ビューの OnDestroy() オーバーライドを調査しましたが、新しいビューが作成される前にこれらが呼び出されていないことがわかりました。あるビューから別のビューに移動するときに、ビューが破棄されることを確認するために離れているため、次のビューが膨張する前にリソースを解放するのに役立ちます。
アプリでこれらのリソースをより適切に管理する方法についてアドバイスをいただければ幸いです。