title: Android memory leak using ActionBar and Spinner navigation
body: <p>My code has a massive memory leak on orientation change. The heap is full after rotating the phone once or twice. I tried to track down the leak for two days now without success.</p>
  
  <p>The application uses SDK 15 (min 14).</p>
  
  <p><code>MainActivity</code> shows an ActionBar with list navigation (<code>NAVIGATION_MODE_LIST</code>). Navigating the spinner replaces the fragment shown.</p>
  
  <p>The code works.</p>
  
  <p><code>ListNavigationItem</code> which contains the information needed to instantiate Fragments:</p>
  
  <pre><code>public class ListNavigationItem
  {
      public final String fragmentClass;
      public final String title; // Used as fragment tag and as title
  
      public ListNavigationItem(String fragmentClass, String title)
      {
          this.fragmentClass = fragmentClass;
          this.title = title;
      }
  
      @Override
      public String toString()
      {
          return title;
      }
  }
  </code></pre>
  
  <p>And finally my (simplified) <code>MainActivity</code>:</p>
  
  <pre><code>public class MainActivity extends Activity implements OnNavigationListener
  {
      private MyApplication app;
      private ArrayAdapter&lt;ListNavigationItem&gt; adapter;
  
      @Override
      protected void onCreate(Bundle savedInstanceState)
      {
          super.onCreate(savedInstanceState);
  
          setContentView(R.layout.main);
  
          app = (MyApplication) getApplicationContext();
  
          ActionBar actionBar = getActionBar();
          actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
          actionBar.setDisplayShowTitleEnabled(false);
          actionBar.setDisplayShowHomeEnabled(false);
  
          adapter = new ArrayAdapter&lt;ListNavigationItem&gt;(this, android.R.layout.simple_spinner_dropdown_item);
          adapter.add(new ListNavigationItem(FirstFragment.class.getName(), "First"));
          adapter.add(new ListNavigationItem(SecondFragment.class.getName(), "Second"));
  
          actionBar.setListNavigationCallbacks(adapter, this);
      }
  
      public boolean onNavigationItemSelected(int itemPosition, long itemId)
      {
          ListNavigationItem item = adapter.getItem(itemPosition);
          if (item == null)
              return false;
  
          Fragment f = getFragmentManager().findFragmentByTag(item.title);
  
          if (f == null)
              f = Fragment.instantiate(this, item.fragmentClass);
          else if (f.isAdded())
              return true;
  
          FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
          fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
          fragmentTransaction.replace(R.id.main_content, f, item.title);
          fragmentTransaction.commit();
  
          return true;
      }
  
      @Override
      protected void onDestroy()
      {
          adapter = null; // Do I need this?
          app = null;
          super.onDestroy();
      }
  }
  </code></pre>
  
  <p>Manifest:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest
      xmlns:android="http://schemas.android.com/apk/res/android"
      package="at.company.app"
      android:versionCode="1"
      android:versionName="1.0"&gt;
  
      &lt;uses-sdk android:minSdkVersion="14" /&gt;
      &lt;uses-sdk android:targetSdkVersion="15" /&gt;
  
      &lt;application
          android:name=".Application"
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"&gt;
  
          &lt;activity
              android:name=".MainActivity"
              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>
  
  <p>A MAT heap analysis says that the class <code>android.content.res.Resources</code> occupies 57% of the available memory, and <code>android.graphics.Bitmap</code> occupies 12%. My fragments, however, contain just a simple <code>TextView</code>.</p>
  
  <p>The MAT histogram shows that there are 4 Objects (Instances, I assume?) of <code>MainActivity</code>. Also, logcat shows that the heap is frequently being emptied after orientation change (GC_CONCURRENT).</p>
  
  <p>The official Dev Guide discourages from using <code>android:configChanges="orientation"</code>. (<a href="http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange" rel="nofollow">Source</a>)</p>
  
  <p>I am relatively new to Java and the Android platform, and I would appreciate any help.</p>