title: How to add a dynamic view to a ListView item at runtime?
body: <p>My problem is that I don't know whether I should use multiple list view or a custom listview item adapter which can grows dynamically. For example, for a particular user, they can have multiple activities:<br>
  - Take a picture<br>
  - Say something<br>
  - Checking in<br>
  - ...  </p>
  
  <p>Apparently, this list can grows as the user has done more activities. Most of the time, I often create a custom item adapter which extends from <code>BaseAdapter</code> and use the <code>ItemHolder</code> pattern as follows:</p>
  
  <pre><code>public class PlaceItemAdapter extends BaseAdapter {
      private Activity        context;
      private List&lt;Place&gt;     places;
      private boolean         notifyChanged = false;
  
      public PlaceItemAdapter(Activity context, List&lt;Place&gt; places) {
          super();
          this.context = context;
          this.places = places;
      }
  
      public int getCount() {
          return places.size();
      }
  
      public Object getItem(int position) {
          return places.get(position);
      }
  
      public long getItemId(int position) {
          return position;
      }
  
      public static class ItemViewHolder {
          TextView nameTextView;
          TextView typesTextView;
          TextView ratingTextView;
          ImageView mapIconImageView;
      }
  
      public View getView(int position, View convertView, ViewGroup parent) {
          ItemViewHolder holder;
          LayoutInflater inflater = context.getLayoutInflater();
          if (convertView == null) {
              convertView = inflater.inflate(R.layout.place_item, null);
              holder = new ItemViewHolder();
              holder.nameTextView = (TextView) convertView.findViewById(R.id.place_item_xml_textview_name);
              holder.typesTextView = (TextView) convertView.findViewById(R.id.place_item_xml_textview_address);
              holder.ratingTextView = (TextView) convertView.findViewById(R.id.place_item_xml_textview_rating);
              holder.mapIconImageView = (ImageView) convertView.findViewById(R.id.place_item_xml_imageview_location_icon);
  
              convertView.setTag(holder);
          }
          else {
              holder = (ItemViewHolder) convertView.getTag();
          }
  
          holder.nameTextView.setText(places.get(position).getName());
          holder.typesTextView.setText(places.get(position).getAddress());
          holder.ratingTextView.setText(Integer.toString(places.get(position).getRating()));
          /*
           * This task is time consuming!
           * TODO: find a workaround to handle the image
           */
          // holder.mapIconImageView.setImageBitmap(DownloadImageHelper.downloadImage(places.get(position).getIconUrl()));
          holder.mapIconImageView.setImageResource(R.drawable.adium);
          return convertView;
      }
  
      public void notifyDataSetChanged() {
          super.notifyDataSetChanged();
          notifyChanged = true;
      }
  }
  </code></pre>
  
  <p>Using this method, the number GUI widgets is fixed which means I can't make my listview item look like the picture below.</p>
  
  <pre><code>    public static class ItemViewHolder {
          TextView nameTextView;
          TextView typesTextView;
          TextView ratingTextView;
          ImageView mapIconImageView;
      }
  </code></pre>
  
  <p>My initial approach was to create a dynamic view nested inside an adapter item, however it will produce duplicate views. To avoid duplicate view, I have set <code>convertView</code> to null which means each time it loads, it will create a new <code>ItemViewHolder</code> which eventually eats up all my memory. :( So how could I handle this situation? A minimal working example would be greatly appreciated.</p>
  
  <p><strong>Duplicate View</strong></p>
  
  <pre><code>public class FriendFeedItemAdapter extends BaseAdapter {
      private List&lt;FriendFeedItem&gt; items;
      private Activity context;
      private static LayoutInflater inflater;
      public ImageLoader imageLoader;
      private ItemViewHolder viewHolder;
  
      public FriendFeedItemAdapter(Activity context, List&lt;FriendFeedItem&gt; items) {
          this.context = context;
          this.items = items;
          inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          imageLoader = new ImageLoader(context.getApplicationContext());
      }
  
      public int getCount() {
          return items.size();
      }
  
      public Object getItem(int position) {
          return items.get(position);
      }
  
      public long getItemId(int position) {
          return position;
      }
  
      public static class ItemViewHolder {
          TableLayout  table;
          ImageView imageViewUserPicture;
          TextView textViewUsername;
          TextView textViewWhatUserDo;
          TextView textViewWhere;
          TextView textViewTime;
          ImageView imageViewSnapPictureBox;
          TextView textViewWriteOnWallMessageBox;
      }
  
      public View getView(int position, View convertView, ViewGroup parent) {
          if (convertView == null) {
              convertView = inflater.inflate(R.layout.friend_list_feed_item, null);
              viewHolder = new ItemViewHolder();
              viewHolder.table = (TableLayout) convertView.findViewById(R.id.friend_list_feed_item_xml_tablelayout_table);
              viewHolder.imageViewUserPicture = (ImageView) convertView.findViewById(R.id.friend_list_feed_item_xml_imageview_user_picture);
              viewHolder.textViewUsername = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_username);
              viewHolder.textViewWhatUserDo = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_what_user_do);
              viewHolder.textViewWhere = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_where);
              viewHolder.textViewTime = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_at_what_time);
  
              convertView.setTag(viewHolder);
          }
          else {
              viewHolder = (ItemViewHolder) convertView.getTag();
          }
  
          imageLoader.displayImage(items.get(position).getFriendPictureUrl(), viewHolder.imageViewUserPicture);
          viewHolder.textViewUsername.setText(items.get(position).getFriendName());
          viewHolder.textViewWhere.setText("at " + items.get(position).getPlaceName());
          viewHolder.textViewTime.setText("@" + items.get(position).getActivityTime());
  
          if (items.get(position).getChallengeType() == Challenge.Type.CHECK_IN) {
              viewHolder.textViewWhatUserDo.setText("has checked in.");
          }
          else if (items.get(position).getChallengeType() == Challenge.Type.SNAP_PICTURE) {
              viewHolder.textViewWhatUserDo.setText("has snap a picture.");
              // add picture box
              View rowView = inflater.inflate(R.layout.snap_picture_row_item, null);
              viewHolder.imageViewSnapPictureBox = (ImageView) rowView.findViewById(R.id.snap_picture_row_item_xml_imageview_picture);
              imageLoader.displayImage(items.get(position).getActivitySnapPictureUrl(), viewHolder.imageViewSnapPictureBox);
              viewHolder.table.addView(rowView);
          }
          else if (items.get(position).getChallengeType() == Challenge.Type.WRITE_ON_WALL) {
              viewHolder.textViewWhatUserDo.setText("has written a message on wall.");
              // add message box
              View rowView = inflater.inflate(R.layout.write_on_wall_row_item, null);
              viewHolder.textViewWriteOnWallMessageBox = (TextView) rowView.findViewById(R.id.write_on_wall_row_item_xml_textview_wall_message);
              viewHolder.textViewWriteOnWallMessageBox.setText(items.get(position).getActivityComment());
              viewHolder.table.addView(rowView);
          }
          else if (items.get(position).getChallengeType() == Challenge.Type.QUESTION_ANSWER) {
              viewHolder.textViewWhatUserDo.setText("has answered a question.");
          }
          else { // Challenge.Type.OTHER
              viewHolder.textViewWhatUserDo.setText("has done some other challenges.");
          }
  
          return convertView;
      }
  }
  </code></pre>
  
  <p><strong>Extensive Memory Usage</strong></p>
  
  <pre><code>public View getView(int position, View convertView, ViewGroup parent) {
          ItemViewHolder holder = null;
          LayoutInflater inflater = context.getLayoutInflater();
  
          convertView = inflater.inflate(R.layout.friend_list_feed_item, null);
          // create holder
          holder = new ItemViewHolder();
          // default field
          holder.table = (TableLayout) convertView.findViewById(R.id.friend_list_feed_item_xml_tablelayout_table);
          holder.imageViewUserPicture = (ImageView) convertView.findViewById(R.id.friend_list_feed_item_xml_imageview_user_picture);
          holder.textViewUsername = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_username);
          holder.textViewWhatUserDo = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_what_user_do);
          holder.textViewWhere = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_where);
          holder.textViewTime = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_at_what_time);
          convertView.setTag(holder);
  
          holder.imageViewUserPicture.setImageURI(items.get(position).getFriendPictureUri());
          holder.textViewUsername.setText(items.get(position).getFriendName());
          holder.textViewWhere.setText("at " + items.get(position).getPlaceName());
          holder.textViewTime.setText("@" + items.get(position).getActivityTime());
  
          if (items.get(position).getChallengeType() == Challenge.Type.CHECK_IN) {
              holder.textViewWhatUserDo.setText("has checked in.");
          }
          else if (items.get(position).getChallengeType() == Challenge.Type.SNAP_PICTURE) {
              holder.textViewWhatUserDo.setText("has snap a picture.");
              // add picture box
              View rowView = inflater.inflate(R.layout.snap_picture_row_item, null);
              holder.imageViewSnapPictureBox = (ImageView) rowView.findViewById(R.id.snap_picture_row_item_xml_imageview_picture);
              holder.imageViewSnapPictureBox.setImageURI(items.get(position).getActivitySnapPictureUri());
              holder.table.addView(rowView);
          }
          else if (items.get(position).getChallengeType() == Challenge.Type.WRITE_ON_WALL) {
              holder.textViewWhatUserDo.setText("has written a message on wall.");
              // add message box
              View rowView = inflater.inflate(R.layout.write_on_wall_row_item, null);
              holder.textViewWriteOnWallMessageBox = (TextView) rowView.findViewById(R.id.write_on_wall_row_item_xml_textview_wall_message);
              holder.textViewWriteOnWallMessageBox.setText(items.get(position).getActivityComment());
              holder.table.addView(rowView);
          }
          else if (items.get(position).getChallengeType() == Challenge.Type.QUESTION_ANSWER) {
              holder.textViewWhatUserDo.setText("has answered a question.");
          }
          else { // Challenge.Type.OTHER
              holder.textViewWhatUserDo.setText("has done some other challenges.");
          }
  
          return convertView;
      }
  </code></pre>
  
  <p><img src="https://i.stack.imgur.com/QRa5L.png" alt="enter image description here"></p>
  
  <p><img src="https://i.stack.imgur.com/DVwbn.png" alt="enter image description here"></p>