title: Memory leak in very simple app
body: <p>An app I am working on is leaking memory.  As far as I can tell I am doing everything suggested in:  <a href="http://developer.android.com/resources/articles/avoiding-memory-leaks.html" rel="nofollow">http://developer.android.com/resources/articles/avoiding-memory-leaks.html</a></p>
  
  <p>I've cut my app down to a very simple app which does nothing but set the background image.  Every time I do a screen orientation change the app leaks 30k-50k of memory.</p>
  
  <p>So I am suspicious of the following:</p>
  
  <p>SetContentView()
  and 
  findViewById()</p>
  
  <p>Do I need to do something in the onDestroy() related to these calls, to decouple them from the Activity?</p>
  
  <p>Also I have a couple of questions.  In onDestroy() I call setBackgroundResource(0).  I believe if I do not do this, the Drawable for the background bitmap will maintain a callback to the view and this will cause a leak of the entire context.  Is this true?  Adding this call to the onDestroy() certainly seemed to make a big difference in the magnitude of the leaks.  In the view constructors I try to remove some references to the activity by making the super() calls with the Application context, as opposed to the activity context.  Does this actually provide this benefit or does it matter at all?  Are there side effects to doing this that I should be aware of?</p>
  
  <p>Code and XML follows:  At this point I really don’t see why it should be leaking memory.  Any enlightenment would be greatly appreciated.</p>
  
  <p>MemLeak.java </p>
  
  <pre><code>package randombrand.MemLeak;
  
  import randombrand.MemLeak.R;
  import randombrand.MemLeak.MLView;
  import android.app.Activity;
  import android.os.Bundle;
  import android.util.Log;
  
  public class MemLeak extends Activity {
  
      private MLView mmlView;
      private static final String strmlBundle = "Mem Leak";
  
      @Override
      public void onCreate(Bundle icicle) {
          super.onCreate(icicle);
          setContentView(R.layout.memleak_layout);
          mmlView = (MLView) findViewById(R.id.viewMemLeak);
          try {
              mmlView.Init(this);
              SetBackgroundBitmap();
          } catch (Exception ex) {
              Log.e(strmlBundle, "Failed to launch Mem Leak." + ex);
              this.finish();
          }
          if (icicle == null) {
              mmlView.SetActive(true);
          } else {
              Bundle bundle = icicle.getBundle(strmlBundle);
              if (bundle != null) {
                  mmlView.SetActive(true);
                  mmlView.invalidate();
              } else {
                  mmlView.SetActive(false);
              }
          }
      }
  
      @Override
      protected void onPause() {
          super.onPause();
          mmlView.SetActive(false);
      }
  
      @Override
      protected void onResume() {
          super.onResume();
          mmlView.SetActive(true);
      }
  
      private void SetBackgroundBitmap() {
          mmlView.setBackgroundResource(R.drawable.dark_background);
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
          mmlView.setBackgroundResource(0);
      }
  }
  </code></pre>
  
  <p>MLView.java</p>
  
  <pre><code>package randombrand.MemLeak;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.os.Handler;
  import android.os.Message;
  import android.util.AttributeSet;
  import android.view.View;
  
  public class MLView extends View {
  
      private static final long ltFpDrawDelay = 66;
      Context mContextApp;
      // true when we are not sleeping in the background
      private boolean mfActive = false;
  
      public MLView(Context context, AttributeSet aSet) {
          super(context.getApplicationContext(), aSet);
      }
  
      public MLView(Context context, AttributeSet aSet, int nStyle) {
          super(context.getApplicationContext(), aSet, nStyle);
      }
  
      public void Init(MemLeak mLeak) {
          mContextApp = mLeak.getApplicationContext();
          SetActive(true);
      }
  
      public void Update() {
          mRedrawHandler.sleep(ltFpDrawDelay);
      }
  
      public void SetActive(boolean fActive) {
          mfActive = fActive;
          if (fActive) Update();
      }
  
      @Override
      public void onDraw(Canvas canvas) {
          super.onDraw(canvas);
      }
  
      private RedrawHandler mRedrawHandler = new RedrawHandler();
  
      class RedrawHandler extends Handler {
  
          @Override
          public void handleMessage(Message msg) {
              MLView.this.Update();
              MLView.this.invalidate();
          }
  
          public void sleep(long ltMillis) {
              this.removeMessages(0);
              sendMessageDelayed(obtainMessage(0), ltMillis);
          }
      }
  }
  </code></pre>
  
  <p>memleak_layout.java</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"&gt;
  
      &lt;randombrand.MemLeak.MLView
          android:id="@+id/viewMemLeak"
          android:layout_width="fill_parent" 
          android:layout_height="fill_parent" /&gt;
  
  &lt;/FrameLayout&gt;    
  </code></pre>
  
  <p>AndroidManifest.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="randombrand.MemLeak"
        android:versionCode="1"
        android:versionName="1.0"&gt;
      &lt;uses-sdk android:minSdkVersion="5" /&gt;
  
      &lt;application android:icon="@drawable/icon" android:label="@string/app_name"
               android:debuggable="true"&gt;
          &lt;activity android:name="MemLeak"
                   android:launchMode="singleInstance"
                   android:label="@string/app_name"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
      &lt;/application&gt;
  &lt;/manifest&gt;
  </code></pre>