Android View中setTag的二三事

每一个APP,都离不开View的使用,小到一个登陆注册页面,大到复杂的网上商城,都是View使用的具体体现。

往往我们使用View,其实就是为了向用户展示一定的数据,因此,view的使用又总是离不开数据的。基本很多人的做法都会把数据以及view分开,但是其实在Android开发的view中已经有api接口可以完成一定量数据的存储了,这就是——View.setTag()以及View.getTag()

### 什么是setTag

setTag()是做什么的呢?SDK的解释为:

Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure.

Tag从本质上来讲是就是相关联的view的额外的信息。它们经常用来存储一些view的数据,这样做非常方便而不用存入另外的单独结构。

###setTag的一些使用场景

setTag的这个api其实隐藏的比较的深,甚至在笔者之前学习的基础教程中是完全没有提到过的(好吧,也有可能是我的基础教材选的不好)。我第一次接触这一个api是在自己在尝试的完成自己的课程设计项目时,在项目中使用了**ListView**展示一系列的数据,当时的数据量是比较的大,同时每一个listItem中的view也是比较的复杂,不仅有头像,有用户名,有标题,有内容,甚至是有图片等等。

复杂的view的创建是会比较消耗机器的性能的,大量复杂的view就不用说了。因此我便在寻找方法优化list的时候,接触了setTag().在接触Android开发以来,setTag()使用的最多的场景基本就是ListView,GridView,RecycleView,ViewPage,Gallery啊等等一系列类似用于展示大量重复的View的控件上。*因为这些控件的数据量一般会比较多,例如在夜夜项目中照片瀑布流中,一页就是30张照片,加载十几页就是几百张的图片,如果不对资源加以回收的话,即使是刘威的一加3有6G内存也都不够用~*

因此,这一些控件基本都会对视图判断是否在可视的范围,从而决定回不回收资源。**那么,问题就来了,当被回收的view再一次出现在世人的眼前的时候,机器是不是需要重新绑定数据,重新加载资源,重新绘制view?**问题的答案是肯定的,**当然要!**(都已经被回收了)那么明明已经使用过的view再来一次也要重新开始绘制,那样不是一直在重复同样的动作?**特别是在一些列表或是网格的视图中,明明每一个item都是长得一样的,也是要重复创建?**同样的事,重复的做,那就是在无谓的消耗机器性能了。**因此,我们要做的是让同样的事,只做一次就好!**

通过观察,我们可以发现,其实无论是ListView,GridView,RecycleView,ViewPage,还是Gallery,它们的使用都是离不开adapter,每一个子item的创建也是在adapter中的getView()中完成的,因此,我们**要开刀的就是adapter的getView()**.

在夜夜项目中的经理列表,如下:

![](/content/images/2016/07/726155124686308457.jpg)

每一个itemView的布局都是一样的,都包括了经理头像,名字,常去酒吧,性别,热度,驻场,以及三张小的现场图片。那么,该经理listView的adapter中getView()最正常的写法如下:

![](/content/images/2016/07/----_20160722011238.png)

其实,在itemView相同的情况下,每一次创建itemView的时候都要重复的去绑定控件,须知,项目中R文件中的id可是非常very多的,这样重复的findViewById是很消耗性能的,特别在控件还很多,一个list中的itemView也很多的情况下。那么,我们就要对绑定控件这一部分进行优化。

首先我们通过查询setTag()的源码就可以知道

![](/content/images/2016/07/----_20160722011826.png)

setTag()是把Object对象作为参数对view进行存储的。也就是说,我们要把一个itemView中的控件抽取成一个Object,在此,我们创建了一个ViewHolder

![](/content/images/2016/07/----_20160722012050.png)

然后修改getView()

![](/content/images/2016/07/----_20160722012234.png)

在第一次创建itemView的时候,完成对控件的绑定,同时吧控件作为一个object--holder,把它通过setTag()存到itemView中,再第二次使用的时候就可以通过getTag()把holder取出来直接使用,也就是说,在list中itemView相同的情况下,我们只进行了一次的控件资源绑定。是不是就省了很多?

**这样的方式是适合用所有类似的控件的。包括上文提及的GridView,RecycleView,ViewPage,Gallery等,具体可以自己发挥**

### 那么,问题又来了!

在夜夜项目中开发在线聊天IM的时候,**聊天界面的消息也是由listView实现的,但是,ItemView长得不一样啊???itemView有文本消息的,有图片消息的,也有分享的名片、酒水套餐等,一个ViewHolder根本hold不住了喂!有可能上一次创建的文本消息itemView,这一次却是要图片消息的itemView了!**

其实,这个问题根本**不用担心!!!**我们翻一翻源码又发现,还有这个东西:setTag(key,object)

![](/content/images/2016/07/----_20160722013426.png)

也就说,其实一个view中是可以setTag多个object的,我们只需要在setTag的时候指定key,只有再通过getTag(key)就可以取出相对应的object了,界面再多类型的itemView,再多不同的holder也不怕了呢~

那么我为什么又要拿出来单独说呢?因为**这里面有坑!**

假如你这样子使用:

> `converView.setTag("text",textHolder);`

`converView.setTag("pic",picHolder);`

`converView.setTag(100,shareHolder);`

>

那么,恭喜你,你的项目要开始Crash了,开始抛出IllegalArgumentException的问题了~因为在SDK中有这样子说过:

>*“ The specified key should be an id declared in the resources of the application to ensure it is unique (see the ID resource type). Keys identified as belonging to the Android framework or not associated with any package will cause an IllegalArgumentExceptionto be thrown.”*

**也就是说你的key必须是唯一的!!!**

那么我们要怎么实现唯一的key呢?其实我们可以把key定义在资源文件中,再由编译器生成对应的,唯一的id!因此我们可以这样写在项目的资源res/values/string.xml中:

![](/content/images/2016/07/----_20160722014903.png)

然后直接:

`converView.setTag(R.id.tag_text,textHolder);`

就可以了,取值的时候:

`textHolder = converView.getTag(R.id.tag_text);`

然后,你就可以愉快的撸代码啦~

###### 至此,全文基本完!

*edit by: 陈育生*

如果这篇文章又帮到你的话,请点一下‘喜欢’,我会更努力的创作的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容