title: Listview memory leak
body: <p>I have a simple list view with adapter.
  I create 10+ listviewitems dynamically. Then I scroll up and down again and again and again....
  I can see that available memory keeps going down...</p>
  
  <p>Where do I need to free and what?
  Note - there is an imageview - but in my test I have not used any images so it is View.GONE.</p>
  
  <p>Also - with which tool can I profile the memory usage on the android. I have found yourKit,but how do I configure it for the android (I run the application on the device)/</p>
  
  <p>The Activity class</p>
  
  <pre><code>package org.BJ.Food4All.Activities.NewRecipe;
  
  
  import org.BJ.Food4All.R;
  import org.BJ.Food4All.Recipe;
  import org.BJ.Food4All.Recipe.Instruction;
  import org.BJ.Food4All.Activities.RecipeBook.RecipeInstructionsListViewAdapter;
  import org.BJ.Food4All.Activities.RecipeBook.SharedData;
  import org.BJ.Food4All.utils.CameraUtil;
  import org.BJ.Food4All.utils.ImageUploadItem;
  
  import android.app.ListActivity;
  import android.content.Intent;
  import android.graphics.Bitmap;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.ContextMenu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.ContextMenu.ContextMenuInfo;
  import android.view.View.OnClickListener;
  import android.widget.AdapterView;
  import android.widget.EditText;
  
  public class Instructions extends ListActivity implements OnClickListener
  {
      private final static String mTAG = "Instructions";
      private EditText mInstructionEditText = null;
      private RecipeInstructionsListViewAdapter mListViewAdapter = null;
      private Recipe mEditRecipe = PrivateResources.GetRecipe();
  
      private CameraUtil  mCameraUtil = new CameraUtil(this);
  
      private int mSelectedEntryIndex = -1;
  
      @Override
      protected void onCreate(Bundle savedInstanceState)
      {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.new_recipe_instruction_tab);
  
          mInstructionEditText = (EditText)findViewById(R.id.newRecipeInstructionEditTextId);
          View addInstructionButton = findViewById(R.id.naddInstructionButtonId);
  
          // Sanity check
          if(mInstructionEditText == null || addInstructionButton == null)
          {
              Log.e(mTAG, "NULL pointers");
              // secure exit
              finish();
          }
  
          // Set up click listeners for all the buttons
          addInstructionButton.setOnClickListener(this);
  
          mListViewAdapter = new RecipeInstructionsListViewAdapter(this, R.layout.recipes_instruction_list_single_view_entry, mEditRecipe.GetInstructions());
  
          setListAdapter(mListViewAdapter);
  
          registerForContextMenu(getListView());
      }
  
      public void onClick(View v)
      {
          switch(v.getId())
          {
              case R.id.naddInstructionButtonId:
                  AddInstructionToRecipe(v);
                  break;
  
              default:
                  Log.e(mTAG, "Invalid ID:" + v.getId());
                  // secure exit
                  finish();
  
          }
      }
  
      private void AddInstructionToRecipe(View v)
      {
          String instructionText = mInstructionEditText.getText().toString();
  
          if(instructionText == null)
          {
              return;
          }
  
          Instruction newInstruction = new Instruction(   mEditRecipe.GetInstructions().size() + 1,   // Index
                                                          instructionText,                            // The instruction
                                                          null,
                                                          true);
  
          if( mEditRecipe.AddInstruction(newInstruction) != true)
          {
              // TODO - ERROR
          }
          else
          {
              mListViewAdapter.notifyDataSetChanged();
          }
      }
  
      /*
       * (non-Javadoc)
       * @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)
       */
      @Override
      public void onCreateContextMenu(ContextMenu menu, 
                                      View v,
                                      ContextMenuInfo menuInfo) 
      {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.instructions_ctx_menu, menu);
  
          super.onCreateContextMenu(menu, v, menuInfo);
      }
  
      /*
       * (non-Javadoc)
       * @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
       */
      @Override
      public boolean onContextItemSelected(MenuItem item) 
      {
          super.onContextItemSelected(item);
  
          AdapterView.AdapterContextMenuInfo menuInfo;
          menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
          mSelectedEntryIndex = menuInfo.position;
  
          switch(item.getItemId()) 
          {
              case R.id.deleteId:
                  mEditRecipe.RemoveInstruction(mSelectedEntryIndex);
                  mListViewAdapter.notifyDataSetChanged();
                  return true;
  
              case R.id.takePictureId:
                  mCameraUtil.TakePicture();
                  return true;
          }
  
          return false;
      }
  
      /*
       * (non-Javadoc)
       * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
       */
      @Override
      protected void onActivityResult(int requestCode, 
                                      int resultCode, 
                                      Intent data) 
      {
  //      String imageLocation = mCameraUtil.onActivityResult(requestCode, resultCode, data);
          Bitmap imageBitmap = mCameraUtil.onActivityResult(requestCode, resultCode, data);
          // TODO - switch to parameter passed in the intent!!!! like TakePicture(index);
  //      mEditRecipe.GetInstructions().get( mSelectedEntryIndex ).SetBitmap( imageBitmap ); //SetInstructionImageLocation(imageLocation);
          mSelectedEntryIndex = -1;
  
          // Update the listviewitem with the picture
          mListViewAdapter.notifyDataSetChanged();
      }
  }
  </code></pre>
  
  <p>The adapter class</p>
  
  <pre><code>package org.BJ.Food4All.Activities.RecipeBook;
  
  import java.util.ArrayList;
  
  import org.BJ.Food4All.R;
  import org.BJ.Food4All.Recipe.Instruction;
  import org.BJ.Food4All.utils.GlobalDefs;
  
  import android.content.Context;
  import android.graphics.Bitmap;
  import android.graphics.Color;
  import android.graphics.Typeface;
  import android.net.Uri;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.ViewGroup.LayoutParams;
  import android.widget.ArrayAdapter;
  import android.widget.ImageView;
  import android.widget.ListView;
  import android.widget.TextView;
  
  public class RecipeInstructionsListViewAdapter extends ArrayAdapter&lt;Instruction&gt; 
  {
      private Context mContext;
      private ArrayList&lt;Instruction&gt; mItems;
      private LayoutInflater mInflater;
  
      public RecipeInstructionsListViewAdapter(Context context, int textViewResourceId, ArrayList&lt;Instruction&gt;items) 
      {
          super(context, textViewResourceId, items);
  
          mContext = context;
          mItems  = items;
  
          mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      }
  
      @Override
      public View getView(int position, 
                          View convertView, 
                          ViewGroup parent) 
      {
            ViewHolder holder = new ViewHolder();
  
            if (convertView == null) 
            {
                convertView = mInflater.inflate(R.layout.recipes_instruction_list_single_view_entry, null);
            }
  
            if(super.getItem(position) != null)
            {
                holder.instructionIndex = (TextView) convertView.findViewById( R.id.listUp_RecipeInstructionNumberTextBoxId);
                holder.instructionText = (TextView) convertView.findViewById( R.id.listUp_RecipeInstructionTextTextBoxId);
                holder.instructionImage = (ImageView)convertView.findViewById( R.id.listUp_RecipeInstructionImageViewId);
  
                Typeface tf = Typeface.createFromAsset(mContext.getAssets(), "Eras_Bold.ttf");
                holder.instructionIndex.setTypeface(tf);
                holder.instructionIndex.setTextSize(30);
                holder.instructionIndex.setTextColor(GlobalDefs.GetHeadlineColor());
                holder.instructionIndex.setText( Integer.toString(mItems.get(position).getIndex()));
  
                tf = Typeface.createFromAsset(mContext.getAssets(), "Arial.ttf");
                holder.instructionText.setTypeface(tf);
                holder.instructionText.setTextSize(14);
                holder.instructionText.setTextColor(Color.BLACK);
                holder.instructionText.setText(mItems.get(position).getText());
  
                Bitmap imageBitmap = mItems.get(position).GetBitmap();
  //              String imageLocation = mItems.get(position).GetInstructionImageLocation();
                if(imageBitmap != null)
                {
                    holder.instructionImage.setImageBitmap(imageBitmap);// setImageURI( Uri.parse(imageLocation ));
                    holder.instructionImage.setVisibility(View.VISIBLE);
                }
                else
                {
                    holder.instructionImage.setVisibility(View.GONE);
                }
  
                convertView.setTag(holder);
                convertView.setLayoutParams(new ListView.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
            } 
            else 
            {
            }
  
            return convertView;
      }
  
      @Override
      public boolean isEnabled(int position) 
      {
          return true;
      }
  
      static class ViewHolder 
      {
            TextView  instructionIndex;
            TextView  instructionText;
            ImageView instructionImage;
      }
  }
  </code></pre>