5

したがって、通常使用するよく知られた 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;
    }

ViewHolder クラスは通常次のようになります。

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

私の質問は ViewHolder の実装に関するものです。
1) すべてのフィールドを初期化する代わりにコンストラクタを使用しないのはなぜですか?
2) なぜ保護ではなくデフォルトのアクセス タイプを使用するのですか (実際にはプライベートにする必要がありますが、これは JIT によって作成された静的アクセサーのためにパフォーマンスに影響します) まあ、それは継承だけだと思います。
では、なぜ次のパターンが良くないのか (「保護された vs デフォルト」アクセス タイプを除く):

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;
    }
}

ListAdapter の唯一の変更点は次のとおりです。

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

とにかく、コンストラクターを呼び出す必要があります。それは単に好みの問題ですか?それとも、このバージョンは何らかの理由で遅くなったり、何らかの形でパフォーマンスに影響を与えたりしますか?

4

3 に答える 3

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 );
      }
   }

そして、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();
  }

getView(...)アダプターのコードをよりシンプルに保ち、最終的な変数の利点があるので、私はこのようにするのが好きです。代わりに保護することで速度が少し向上する可能性がありますが、巨大なリストでもパフォーマンスは十分であることがわかりました。

于 2013-04-16T08:55:38.837 に答える
1

私の意見では、これが最善の方法ですが、コードを変更したいことがあります。ビューを設定している場所にコンストラクターがViewHolderありますが、コードで使用していないことがわかります。私はそれを使用するか、単に削除します。もう1つ、実際には同じ効果を得るより良い方法がありますが、それはAndroid 4以降でのみ機能します:

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

    ImageView mIcon;
    TextView mName;
    if (convertView == null) {
        convertView = LayoutInflater.from(context)
          .inflate(R.layout.my_contact_listing, parent, false);
        mIcon = (ImageView) convertView.findViewById(R.id.contact_icon);
        mName = (TextView) convertView.findViewById(R.id.contact_name);
        convertView.setTag(R.id.contact_icon, mIcon);
        convertView.setTag(R.id.contact_name, mName);
    } else {
        mIcon = (ImageView) convertView.getTag(R.id.contact_icon);
        mName = (TextView) convertView.getTag(R.id.contact_name);
    }

    Contact mContact = getItem(position);
    mName.setText(mContact.getName());
    mIcon.setImageResource(mContact.getIcon());

    return convertView;
}
于 2013-04-16T08:46:52.030 に答える