listview sale de la excepción de memoria, pero sin pérdidas de memoria?

Después de Honeycomb, Google dijo que los mapas de bits son administrados por el montón (se habló deaquí), por lo que si un mapa de bits ya no es accesible, podemos asumir que GC se ocupa de él y lo libera.

Quería crear una demostración que muestre la eficacia de las ideas mostradas para la conferencia listView (desdeaquí), así que hice una pequeña aplicación. La aplicación le permite al usuario presionar un botón, y luego la vista de lista se desplaza hasta la parte inferior, mientras que tiene 10000 elementos, cuyo contenido son los elementos de android.R.drawable (nombre e imagen).

Por alguna razón, me quedo sin memoria aunque no guardo ninguna de las imágenes, así que mi pregunta es: ¿cómo podría ser? ¿Qué es lo que me estoy perdiendo?

He probado la aplicación en un Galaxy S III y, sin embargo, me salgo de las excepciones de memoria si utilizo la versión nativa del adaptador. No entiendo por qué ocurre, ya que no almaceno nada.

Aquí está el código:

public class MainActivity extends Activity
  {
  private static final int LISTVIEW_ITEMS =10000;
  long                     _startTime;
  boolean                  _isMeasuring   =false;

  @Override
  public void onCreate(final Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ListView listView=(ListView)findViewById(R.id.listView);
    final Field[] fields=android.R.drawable.class.getFields();
    final LayoutInflater inflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    // listen to scroll events , so that we publish the time only when scrolled to the bottom:
    listView.setOnScrollListener(new OnScrollListener()
      {
        @Override
        public void onScrollStateChanged(final AbsListView view,final int scrollState)
          {
          if(!_isMeasuring||view.getLastVisiblePosition()!=view.getCount()-1||scrollState!=OnScrollListener.SCROLL_STATE_IDLE)
            return;
          final long stopTime=System.currentTimeMillis();
          final long scrollingTime=stopTime-_startTime;
          Toast.makeText(MainActivity.this,"time taken to scroll to bottom:"+scrollingTime,Toast.LENGTH_SHORT).show();
          _isMeasuring=false;
          }

        @Override
        public void onScroll(final AbsListView view,final int firstVisibleItem,final int visibleItemCount,final int totalItemCount)
          {}
      });
    // button click handling (start measuring) :
    findViewById(R.id.button).setOnClickListener(new OnClickListener()
      {
        @Override
        public void onClick(final View v)
          {
          if(_isMeasuring)
            return;
          final int itemsCount=listView.getAdapter().getCount();
          listView.smoothScrollToPositionFromTop(itemsCount-1,0,1000);
          _startTime=System.currentTimeMillis();
          _isMeasuring=true;
          }
      });
    // creating the adapter of the listView
    listView.setAdapter(new BaseAdapter()
      {
        @Override
        public View getView(final int position,final View convertView,final ViewGroup parent)
          {
          final Field field=fields[position%fields.length];
          // final View inflatedView=convertView!=null ? convertView : inflater.inflate(R.layout.list_item,null);
          final View inflatedView=inflater.inflate(R.layout.list_item,null);
          final ImageView imageView=(ImageView)inflatedView.findViewById(R.id.imageView);
          final TextView textView=(TextView)inflatedView.findViewById(R.id.textView);
          textView.setText(field.getName());
          try
            {
            final int imageResId=field.getInt(null);
            imageView.setImageResource(imageResId);
            }
          catch(final Exception e)
            {}
          return inflatedView;
          }

        @Override
        public long getItemId(final int position)
          {
          return 0;
          }

        @Override
        public Object getItem(final int position)
          {
          return null;
          }

        @Override
        public int getCount()
          {
          return LISTVIEW_ITEMS;
          }
      });
    }
  }

@all: Sé que hay optimizaciones para este código (usando el patrón de diseño convertView y viewHolder) como mencioné en el video de listView realizado por Google. Créeme, sé lo que es mejor; Este es el punto entero del código.

Se supone que el código anterior muestra que es mejor usar lo que usted (y el video) muestra. Pero primero necesito mostrar el camino ingenuo; incluso la forma ingenua debería seguir funcionando, ya que no almaceno los mapas de bits ni las vistas, y ya que Google ha realizado la misma prueba (de ahí que obtuvieron un gráfico de comparación de rendimiento).

Respuestas a la pregunta(4)

Su respuesta a la pregunta