У меня есть простой вид списка с адаптером. Я создаю 10+ listviewitems динамически. Затем я прокручиваю вверх и вниз снова и снова и снова... Я вижу, что доступная память продолжает снижаться...
Где мне нужно бесплатно и что? Заметьте - есть изображение, но в моем тесте я не использовал никаких изображений, поэтому это View.GONE.
Также - с помощью какого инструмента можно профилировать использование памяти на Android. Я нашел вашKit, но как его настроить для Android (я запускаю приложение на устройстве)/
Класс Activity
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();
    }
}
Класс адаптера
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<Instruction> 
{
    private Context mContext;
    private ArrayList<Instruction> mItems;
    private LayoutInflater mInflater;
    public RecipeInstructionsListViewAdapter(Context context, int textViewResourceId, ArrayList<Instruction>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;
    }
}
