web-dev-qa-db-ja.com

ViewHolderパターンでのsetTagおよびgetTagの機能は何ですか?

カスタムリストビューを実装するための簡単なコードスニペットがあります。

私のコードは次のとおりです:

WeatherAdapter.Java:

_public class WeatherAdapter extends ArrayAdapter<weather>{

    Context mcontext; 
    int mlayoutResourceId;    
   weather mdata[] = null;
   View row;

    public WeatherAdapter(Context context, int layoutResourceId, weather[] data) {
        super(context, layoutResourceId, data);
        mlayoutResourceId = layoutResourceId;
       mcontext = context;
        mdata = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      row = convertView;
        WeatherHolder holder = null;

        if(row == null)
        {
            LayoutInflater inflater = ( (Activity) mcontext).getLayoutInflater();
            row = inflater.inflate(mlayoutResourceId, parent, false);

            holder = new WeatherHolder(row);


            row.setTag(holder);

        }
        else
        {
            holder = (WeatherHolder)row.getTag();
        }

        weather w = mdata[position];
        holder.txtTitle.setText(w.mtitle);
        holder.imgIcon.setImageResource(w.micon);

        return row;
    }
_

WeatherHolder.Java

_class WeatherHolder
    {
        ImageView imgIcon;
        TextView txtTitle;


    public WeatherHolder(View v){

          imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
          txtTitle = (TextView)row.findViewById(R.id.txtTitle);

    }
    }
}
_

SOおよびその他のサイトで多くの回答を目にしてきましたが、リストビューのリサイクルメカニズムを理解しました。

また、viewholderから、子ビューをアダプターに保持できるため、findViewById()を何度も呼び出す必要がないことも理解しました。つまり、最適化のためです。

しかし、私はsetTag(holder)およびgetTag()メソッドの混乱のみを持っています。 この質問から 、複数のオブジェクトでキーと値のペアを作成して、それらに簡単にアクセスできるようにすることがわかった。ただし、ここでそれらが必要な理由はわかりません...なぜなら、複数のホルダーオブジェクトがないからです...ホルダーの変数を毎回変更する必要があるだけです。 setTaggetTagを使用せずにここでコーディングできますか?

誰かがsetTaggetTagが「ここ」で何をするかについてよりよく説明できますか?

13
Fenil

tagは、viewsobjectintegerstringなど、好きなものを覚えさせるためのメカニズムです。

したがって、ListViewを初めて作成するときは、convertViewnullです。したがって、新しいconvertViewを作成し、そのreferencesobjectsrowのすべてをviewHolderに入れます。次に、viewHolderをそのconvertViewsetTag)のメモリに保存します。 Androidは、convertViewを受け取り、poolに入れてrecycle itに、passesにもう一度入れます。ただし、そのpoolには十分なconvertViewsがない可能性があるため、新しいconvertViewを再度渡しますnull。したがって、poolAndroidがいっぱいになるまで、この話が繰り返されます。その後、AndroidはプールからconvertViewを受け取り、それをユーザーに渡します。あなたはそれがnullではないことに気づくでしょう。そこで、私が初めてあなたに与えたreferencesのオブジェクトはどこにあるのかと尋ねますか? (getTag)なので、それらを取得して好きなように実行できます。

以下の行の詳細

but its pool may not have enough convertViews so it again passes a new convertView thats null

poolを作成しようとしているとき、Android listViewは空です。したがって、listViewの最初の項目については、表示する必要があるconvertViewを送信します。その後、Androidはそれをpoolに保存するため、poolにはconvertViewが1つだけ含まれるようになります。作成するlistViewの2番目の項目の場合Androidには実際には1つの要素があり、その要素が最初の項目であり、現在表示されているため、プールを使用できません。別のconvertViewを渡す必要があります。このプロセスは、Androidが現在表示されていないconvertView内にpoolを見つけて渡すまで繰り返されます。

Androidは、リストをスクロールするときにホルダーを使用して、画面がいっぱいになるまで各行を膨らませます。

25
mmlooloo

別の視点から見てみましょう:

enter image description here

ヘリコプターが「」であり、ロープは "setTag"であり、以下のcarは "WeatherHolder 「しかし、ヘリコプターのパイロットはその車の中にいて、彼/彼女は "有線リモート"を使用してヘリコプターを制御している人です。

「setTag」であるロープをカットしても、ヘリコプターは飛行しますが、パイロットが地面に落ちているため、パイロットはそれを制御できなくなりました。 (Javaでは、オブジェクトがその参照を失うと、ガベージコレクターがそれを収集してメモリから解放します)。

パイロットが座っている場所でヘリコプターが飛行しようとしているときにロープを車に取り付けたり取り付けなかったりした場合-「ワイヤードリモート」を使用しているため、ヘリコプターのコントロールを失う可能性があります。

私はこの助けを願っています:)。

17
neferpitou

しかし、なぜここでそれらが必要なのかわかりません...なぜなら、複数のホルダーオブジェクトがないからです

これはあなたが間違っているところです-ビューごとに1つのホルダーがあります(別名表示またはキャッシュされたListViewエントリ)。

2
Andrew Breen