6

すべてのアクティビティの背景として設定する画像を使用していますが、メモリ オーバーフローの問題が発生し、アプリがクラッシュしていました。現在、アクティビティのpause()およびDestroy()でドローアブルのバインドを解除していますが、戻るボタンを押すと空白の画面が表示されます。では、余分なメモリを使用せずにこれを回避するにはどうすればよいでしょうか。

    protected void onPause(){
    super.onPause();
    unbindDrawables(findViewById(R.id.login_root));
}

protected void onDestroy() {
        unbindDrawables(findViewById(R.id.login_root));
        super.onDestroy();
      }

private void unbindDrawables(View view) {
    System.gc();
    Runtime.getRuntime().gc();
    if (view.getBackground() != null) {
    view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
        unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
    ((ViewGroup) view).removeAllViews();
    }

最初は android:background="@drawable/" を使用してレイアウトを膨らませていましたが、これは常にメモリ オーバーフロー エラーを引き起こし、VM では 10MB を割り当てることができないというメッセージを表示していました (アプリ)。 VM は、unbindDrawables(..) を使用せずに 5MB (app.) を割り当てることはできません。表示される背景画像の品質は明らかに低下しましたが、 png ファイルが 13KB の場合、JVM はリクエストを処理するために 5 MB または 10 MB のスペースをどのように必要としますか?

レイアウトステートメントを onCreate() から onResume() メソッドにシフトしましたが、アプリケーションは戻るボタンを押すと再びメモリ不足になります。

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

  protected void onResume(){
        setContentView(R.layout.home);
        Bitmap bmp;
        ImageView background = (ImageView)findViewById(R.id.iv_home_background);
        InputStream is = getResources().openRawResource(R.drawable.background);
        bmp = BitmapFactory.decodeStream(is);
        background.setImageBitmap(bmp);

         super.onResume();
    }

 protected void onPause(){
        super.onPause();
        unbindDrawables(findViewById(R.id.home_root));
    }


 private void unbindDrawables(View view) {
        System.gc();
        Runtime.getRuntime().gc();
        if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
        ((ViewGroup) view).removeAllViews();
        }
    }
4

2 に答える 2

1

この問題の回避策を見つけました。現在、実行時にビットマップを非常に小さいサイズにスケーリングしてから、内部ストレージに保存しています。プログラムは、実行時にストレージからスケーリングされたビットマップを呼び出し、そこに存在しない場合は、ドローアブルフォルダーから呼び出し、スケーリングし、ストレージに書き込んでから、ビューにバインドします。このように、いつでもunbindDrawablesメソッドを呼び出す必要はなく、アプリケーションは全体を通して応答性を維持します。今のところ私の唯一の懸念はビットマップの品質です。最高の品質で可能な限り最小のサイズを見つけるために、スケーリングサイズをいじくり回す必要があると思います。

于 2012-09-17T09:17:09.703 に答える
0

サブビューごとに GC を呼び出しています。すべてのバインド解除が完了したら、一度だけ呼び出してみてください。

unbindDrawables(findViewById(R.id.login_root));
System.gc();

GC は負荷が高く、頻繁に呼び出しても意味がありません。実際、リークがない場合は、まったく必要ありません。

また、png ファイルのサイズは、メモリ上のビットマップとは関係がないことに注意してください。その詳細については、 http://developer.android.com/training/displaying-bitmaps/index.htmlをご覧ください。

于 2013-09-16T13:54:44.797 に答える