关于ListView中的ViewHolder模式实现优化

Sta*_*tan 5 performance android listview

因此,众所周知的ViewHolder模式通常看起来像(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;
    }
Run Code Online (Sandbox Code Playgroud)

而ViewHolder类通常如下所示:

static class ViewHolder{
    public ImageView previewImage;
    public TextView txtTitle;
    public TextView txtDescription;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是关于ViewHolder的实现.
1)为什么不使用构造函数而不是初始化每个字段?
2)为什么它使用默认访问类型而不是受保护(实际上它必须是私有的,但由于JIT创建的静态访问器,这会影响性能)?好吧,我猜它只是关于继承.
那么为什么以下模式不是更好(不包括"受保护与默认"访问类型):

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并且ListAdapter中唯一的变化是:

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

无论如何,它必须调用构造函数.这只是品味问题吗?或者这个版本在某种程度上是慢的还是以某种方式影响性能?

Sco*_*ris 5

我使用的方法与你的方法非常相似,但我更进一步,因为它ViewHolder是适配器类的私有我通过将视图传递给它的构造函数并在那里设置值,将它紧密地耦合到类中.

    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 );
      }
   }
Run Code Online (Sandbox Code Playgroud)

并在 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();
  }
Run Code Online (Sandbox Code Playgroud)

我喜欢这样做,因为它使我的适配器代码更简单getView(...)并且具有最终变量的好处.我可能会获得一个小的速度提升,使其受到保护,但我发现即使有大量的列表,性能也足够了.

  • 但是他们(像Romain Guy这样的android.developer人员)说ViewHolder必须是静态类(性能问题),如果它的外部类适用于适配器,那么使用私有访问类型也是坏主意(因为它有2b静态它可以'适用于内部适配器)它必须比私有更宽(它们使用我上面提到的默认访问类型). (3认同)

ale*_*ara 2

我认为这只是品味问题。对我来说,它甚至比标准的还要好看。此外,由于使用最终变量,您的版本可能会更快。