型オブジェクトsetTag()
などgetTag()
のメソッドの主な目的は何ですか?View
1つのビューに任意の数のオブジェクトを関連付けることができると考えるのは正しいですか?
型オブジェクトsetTag()
などgetTag()
のメソッドの主な目的は何ですか?View
1つのビューに任意の数のオブジェクトを関連付けることができると考えるのは正しいですか?
類似した一連のビューを生成するとします。OnClickListener
ビューごとに個別にを設定できます。
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
onClick
次に、次のように、ビューが同様のことを行う場合でも、ビューごとに一意のメソッドを作成する必要があります。
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
これは、onClick
パラメータが1つしかないためView
であり、スコープを囲む際にインスタンス変数または最終ローカル変数から他の情報を取得する必要があるためです。私たちが本当に望んでいるのは、ビュー自体から情報を取得することです。
getTag
/を入力してくださいsetTag
:
button1.setTag(1);
button2.setTag(2);
これで、すべてのボタンに同じOnClickListenerを使用できます。
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
それは基本的にビューが思い出を持つための方法です。
いくつか単語を追加したいと思います。
get/setTag(Object)
ViewHolderパターンの特定の場合に使用することは非常に便利なようですが、他の場合に使用する前によく考えておくことをお勧めします。ほとんどの場合、より優れた設計の別のソリューションがあります。
主な理由は、そのようなコードがすぐにサポートできなくなることです。
ビューにタグとして保存するように設計したものは、他の開発者にとっては自明ではありません。メソッドsetTag/getTag
はまったく説明的ではありません。
を格納するだけでObject
、必要なときにキャストする必要がありますgetTag
。後でタグに保存されているオブジェクトのタイプを変更すると、予期しないクラッシュが発生する可能性があります。
実際の話は次のとおりです。多くのアダプター、ビューを使用した非同期操作などを備えた非常に大きなプロジェクトがありました。1人の開発者はコードの彼の部分で決定しset/getTag
ましたが、別の開発者はすでにタグをこのビューに設定していました。結局、誰かが自分のタグを見つけることができず、非常に混乱しました。バグを見つけるのに数時間かかりました。
setTag(int key, Object tag)
見た目ははるかに良く、タグごとに一意のキーを生成できます(idリソースを使用)が、Android<4.0には大きな制限があります。Lintドキュメントから:
Android 4.0より前のバージョンでは、View.setTag(int、Object)の実装により、オブジェクトが静的マップに格納され、値が強く参照されていました。これは、オブジェクトにコンテキストを指す参照が含まれている場合、コンテキスト(他のほとんどすべてを指す)がリークすることを意味します。ビューを渡すと、ビューはそれを作成したコンテキストへの参照を提供します。同様に、ビューホルダーには通常ビューが含まれ、カーソルもビューに関連付けられる場合があります。
setTag()
要件に応じて、およびを使用しgetTag()
てカスタムオブジェクトを設定および取得できます。このsetTag()
メソッドは、型の引数を取りObject
、をgetTag()
返しますObject
。
例えば、
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Web開発者にとって、これはデータと同等のようです-..
ArrayAdapter
これは、カスタム使用に非常に役立ちます。これはある種の最適化です。の代わりに、レイアウトの一部(で表示される)をsetTag
参照するオブジェクトへの参照として使用されます。ListView
findViewById
static class ViewHolder {
TextView tvPost;
TextView tvDate;
ImageView thumb;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.postitem, null);
ViewHolder vh = new ViewHolder();
vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
convertView.setTag(vh);
}
....................
}
IDとは異なり、タグはビューの識別には使用されません。タグは基本的に、ビューに関連付けることができる追加の情報です。これらは、ビューに関連するデータを別の構造に配置するのではなく、ビュー自体に格納するための便宜として最もよく使用されます。
参照:http ://developer.android.com/reference/android/view/View.html
TAGの設定は、ListViewがあり、ビューをリサイクル/再利用したい場合に非常に便利です。このようにして、ListViewは新しいRecyclerViewと非常によく似たものになります。
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if ( convertView == null )
{
/* There is no view at this position, we create a new one.
In this case by inflating an xml layout */
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
convertView.setTag (holder);
}
else
{
/* We recycle a View that already exists */
holder = (ViewHolder) convertView.getTag ();
}
// Once we have a reference to the View we are returning, we set its values.
// Here is where you should set the ToggleButton value for this item!!!
holder.toggleOk.setChecked( mToggles.get( position ) );
return convertView;
}