Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About ViewHolder pattern implementation optimisation in ListView

So the well-known ViewHolder pattern using usually looks like (ListAdapter):

    ...

    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {

        final Album album = albums.get(position);

        ViewHolder viewHolder = null;
        if (convertView==null){
            convertView = inflater.inflate(R.layout.albums_list_item, null);

            final ImageView albumImage = (ImageView) convertView.findViewById(R.id.album_icon);

            final TextView txtTitle = (TextView) convertView.findViewById(R.id.album_title);

            final TextView txtDescription = (TextView) convertView.findViewById(R.id.album_copyright);

            viewHolder = new ViewHolder();
            viewHolder.albumImage = albumImage;
            viewHolder.txtTitle = txtTitle;
            viewHolder.txtDescription = txtDescription;
            convertView.setTag(viewHolder);
        }
        else
            viewHolder = (ViewHolder)convertView.getTag();

        viewHolder.txtTitle.setText(album.getTitle(locale));
        viewHolder.txtDescription.setText(album.getCopyrightInfo(locale));
        ...
        return convertView;
    }

while the ViewHolder class is usually looks like:

static class ViewHolder{
    public ImageView previewImage;
    public TextView txtTitle;
    public TextView txtDescription;
}

My questions is about ViewHolder implementation.
1) Why doesn't it use a constructor instead of initializing every single field?
2) Why does it use the default access type instead of protected (actually it has to be private but this impacts performance due to static accessors created byt JIT)? Well, I guess its about inheritance only.
So why the following pattern is not better (excluding "protected vs default" access type):

protected static class ViewHolder{
    public final ImageView previewImage;
    public final TextView txtTitle;
    public final TextView txtDescription;

    public ViewHolder (final ImageView previewImage,  final TextView txtTitle, final TextView txtDescription){
        this.previewImage = previewImage;
        this.txtTitle = txtTitle;
        this.txtDescription = txtDescription;
    }
}

and the only change in ListAdapter is:

...
final TextView txtDescription = (TextView) convertView.findViewById(R.id.album_copyright);
viewHolder = new ViewHolder(albumImage, txtTitle, txtDescription);
convertView.setTag(viewHolder);
...

Anyway it must call a constructor. Is it just a matter of taste? Or is this version slower somehow or does it impact performance in some way?

like image 679
Stan Avatar asked Apr 16 '13 08:04

Stan


2 Answers

I use an approach very similar to yours but I take it one step further, because the ViewHolder is private to the adapter class I tightly couple it to the class by passing in the view to it's constructor and setting the values there e.g.

    private class ViewHolder
    {
      protected final ImageView image;
      protected final TextView  title;
      protected final TextView  status;

      public ViewHolder( final View root )
      {
         image = (ImageView) root.findViewById( R.id.artist_image );
         title = (TextView) root.findViewById( R.id.artist_title );
         status = (TextView) root.findViewById( R.id.artist_status );
      }
   }

And in getView(...)

 View row = convertView;

  if ( null == row || null == row.getTag() )
  {
     row = inflater.inflate( R.layout.adapter_artists, null );
     holder = new ViewHolder( row );
     row.setTag( holder );
  }
  else
  {
     holder = (ViewHolder) row.getTag();
  }

I like doing it this way because it keeps my adapter code simpler in getView(...) and has the benefit of final variables. I'd probably get a minor speed boost making it protected instead but I find the performance is adequate even with huge lists.

like image 149
ScouseChris Avatar answered Sep 28 '22 04:09

ScouseChris


I thinks that it is just mater of taste. As for me it is even looks better then standard one. Also your version probably will be potentially faster because of using final variables.

like image 42
alexandr.opara Avatar answered Sep 28 '22 03:09

alexandr.opara