android - View的setTag()getTag()方法的主要目的是什么?
这种方法的主要目的是setTag()和getTag()的View类型对象的主要目的是什么?
我是否正确地认为我可以将任意数量的对象与单个视图相关联?
8个解决方案
587 votes
假设你生成了一堆相似的视图。 您可以为每个视图单独设置getTag:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
然后,您必须为每个视图创建一个独特的getTag方法,即使它们执行类似的操作,例如:
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
这是因为getTag只有一个参数,即setTag,它必须从封闭范围内的实例变量或最终局部变量中获取其他信息。 我们真正想要的是从视图本身获取信息。
输入getTag/setTag:
button1.setTag(1);
button2.setTag(2);
现在我们可以为每个按钮使用相同的OnClickListener:
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
它基本上是一种观赏记忆的方式。
Matthew Willis answered 2019-03-31T09:43:29Z
110 votes
我想补充几句话。
虽然在ViewHolder模式的特定情况下使用get/setTag(Object)似乎非常有用,但我建议在其他情况下使用它之前要三思而后行。 几乎总是有另一个好的设计解决方案。
主要原因是代码很快就变得不受支持了。
对于其他开发人员而言,您设计为在视图中存储为标记的内容并不明显。 方法setTag / getTag根本不具有描述性。
它仅存储setTag(int key, Object tag),因此当您想要getTag时需要强制转换。当您决定更改标记中存储对象的类型时,可能会出现意外崩溃。
这是来自现实生活的故事。 我们有一个非常大的项目,包含很多适配器,带有视图的异步操作等等。 一位开发人员在他的部分代码中决定使用setTag(int key, Object tag),但另一位开发人员已经为此视图设置了标记。 最后有人找不到自己的标签而且非常困惑。 花了我们几个小时来找到这个bug。
setTag(int key, Object tag)看起来好多了,因为你可以为每个标签生成唯一的密钥(使用id资源),但是对于Android<4.0。 来自Lint文档:
在Android 4.0之前,执行View.setTag(int,Object) 将对象存储在静态地图中,其中值为 强烈引用。 这意味着如果对象包含任何对象 指向上下文的引用,上下文(指向 几乎所有其他东西)都会泄漏。 如果您传递视图,则视图 提供对创建它的上下文的引用。 同样,观点 持有者通常包含视图,有时也包含游标 与观点相关联。
Andrei Buneyeu answered 2019-03-31T09:44:48Z
24 votes
我们可以使用setTag()和getTag()来根据我们的要求设置和获取自定义对象。 setTag()方法采用类型Object的参数,并且getTag()返回Object。
例如,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Ramkailash answered 2019-03-31T09:45:19Z
17 votes
对于Web开发人员来说,这似乎等同于数据 - ..
Oren answered 2019-03-31T09:45:47Z
14 votes
这对于自定义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);
}
....................
}
shubniggurath answered 2019-03-31T09:46:17Z
11 votes
与ID不同,标签不用于标识视图。 标签本质上是可以与视图相关联的额外信息。 它们通常用作存储与视图本身中的视图相关的数据的便利,而不是将它们放在单独的结构中。
参考:[http://developer.android.com/reference/android/view/View.html]
Saad Bilal answered 2019-03-31T09:46:54Z
10 votes
当您拥有ListView并希望回收/重用视图时,设置TAG非常有用。 通过这种方式,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;
}
answered 2019-03-31T09:47:23Z
0 votes
代码已添加,图像已添加到数据库中我无法查询或从数据库中显示它你可以帮忙。谢谢
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
open_btn = (Button) findViewById(R.id.open);
save_btn = (Button) findViewById(R.id.save);
open_Img = (ImageView) findViewById(R.id.openImage);
saveImg = (ImageView) findViewById(R.id.saveImage);
}
public void save(View view) {
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, 100);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == RESULT_OK) {
Uri uri = data.getData();
saveImg.setImageURI(uri);
bitmap = ((BitmapDrawable)saveImg.getDrawable()).getBitmap();
byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,100,byteArrayOutputStream);
encodeImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(),Base64.DEFAULT);
}
}
public void open(View view) {
byte[] bytes =Base64.decode(encodeImage,Base64.DEFAULT);
Bitmap decodBitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
open_Img.setImageBitmap(decodBitmap);
}
Mustafa answered 2019-03-31T09:47:53Z