SetTag()的ViewTag()方法的主要目的是什么?

Viewtypes对象的setTag()getTag()等方法的主要用途是什么?

我是否认为我可以将任何数量的对象与单个视图关联?

假设您生成了一堆相似的视图。 您可以OnClickListener为每个视图设置一个OnClickListener

 button1.setOnClickListener(new OnClickListener ... ); button2.setOnClickListener(new OnClickListener ... ); ... 

然后,您必须为每个视图创build一个独特的onClick方法,即使他们做了类似的事情,如:

 public void onClick(View v) { doAction(1); // 1 for button1, 2 for button2, etc. } 

这是因为onClick只有一个参数,一个View ,它必须从封装范围的实例variables或最终局部variables中获取其他信息。 我们真正想要的是从自己的观点获得信息。

inputgetTag / setTag

 button1.setTag(1); button2.setTag(2); 

现在我们可以为每个button使用相同的OnClickListener:

 listener = new OnClickListener() { @Override public void onClick(View v) { doAction(v.getTag()); } }; 

这基本上是观点有回忆的一种方式。

我想补充几句话。

尽pipe使用get/setTag(Object)在ViewHolder模式的特殊情况下似乎非常有用,但我build议在使用它之前再考虑一下。 几乎总是有另一个好的devise解决scheme。

主要原因是代码很快就变得不可支持。

  • 对于其他开发人员而言,您devise的视图标签是不明显的。 setTag / getTag方法根本没有描述性。

  • 它只存储一个Object ,所以当你想要getTag时候需要getTag 。 稍后当您决定更改标记中的存储对象的types时,您可能会意外崩溃。

  • 这是现实生活中的故事。 我们有一个非常大的项目,有很多适配器,有视图的asynchronous操作等等。 一个开发人员决定在他的代码中set/getTag ,但另一个开发人员已经为此视图设置了标签。 最终有人找不到自己的标签,很困惑。 这花了我们几个小时来find这个错误。

setTag(int key, Object tag)看起来好多了,因为你可以为每个标签(使用id资源 )生成唯一的键值,但是Android <4.0有一个很大的限制。 从Lint文档:

在Android 4.0之前,View.setTag(int,Object)的实现会将这些对象存储在一个静态映射中,在这个静态映射中这些值被强引用。 这意味着如果对象包含任何指向上下文的引用,则上下文(指向其他所有内容)将会泄漏。 如果你传递一个视图,视图提供了创build它的上下文的引用。 类似地,视图持有者通常包含一个视图,游标有时也与视图相关联。

我们可以使用setTag()getTag()来设置和获取自定义对象。 setTag()方法接受Objecttypes的参数, 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

当你有一个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; } 

代码被添加,图像被添加到数据库我无法查询或从数据库中显示您可以提供帮助。 谢谢

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

}