OutOfMemoryError when loading activities

后端 未结 3 1104
挽巷
挽巷 2021-01-03 09:26

I have a quite simple activity like this :

public class SurvivalActivity extends Activity {
    private static final String KEY_LAYOUT_ID = \"SurvivalLayoutI         


        
3条回答
  •  一生所求
    2021-01-03 10:01

    I'm sorry that the answer of this question wasn't actually possible to have with the elements I gave in my question.

    Indeed, as mentioned in another question here: Why are all my bitmaps upsampled 200%?, I put my pictures in the drawable folder, which, on a xhdpi screen like mine, will cause Android to upsample everything twice (to match xhdpi against mdpi), and will result in a 400% memory usage (twice the width and twice the height so 4 times as many pixels).

    One more thing, since I don't want the user to be able to go back (see the finish() right after the startActivity()), here's what I put in the onPause():

    private void unbindDrawables(View view) {
        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();
        }
    }
    

    This is some code I got here on StackOverflow (for example here: Drawable vs Single reusable Bitmap better with memory?).

    Here are my remarks about this code and why every line is important:

    • The setCallback(null) removes the reference to the activity, so that it can be garbage collected. If you don't do this, all the views will stay in memory.
    • You also need to call it from onPause, because onDestroy is not guaranteed to be called.
    • You may need to cause a garbage collection after this, in order to help the GC understand that some references to objects that were made orphans and that can be GC'd. Just call System.gc().

    This is the resulting onPause code, with the main layout of your activity having the id top_layout:

    @Override
    protected void onPause() {
        super.onPause();
        unbindDrawables(findViewById(R.id.top_layout));
        System.gc();
    }
    

提交回复
热议问题