android listview settag,Android View中setTag的二三事
每一個APP,都離不開View的使用,小到一個登陸注冊頁面,大到復(fù)雜的網(wǎng)上商城,都是View使用的具體體現(xiàn)。
往往我們使用View,其實(shí)就是為了向用戶展示一定的數(shù)據(jù),因此,view的使用又總是離不開數(shù)據(jù)的。基本很多人的做法都會把數(shù)據(jù)以及view分開,但是其實(shí)在Android開發(fā)的view中已經(jīng)有api接口可以完成一定量數(shù)據(jù)的存儲了,這就是——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從本質(zhì)上來講是就是相關(guān)聯(lián)的view的額外的信息。它們經(jīng)常用來存儲一些view的數(shù)據(jù),這樣做非常方便而不用存入另外的單獨(dú)結(jié)構(gòu)。
###setTag的一些使用場景
setTag的這個api其實(shí)隱藏的比較的深,甚至在筆者之前學(xué)習(xí)的基礎(chǔ)教程中是完全沒有提到過的(好吧,也有可能是我的基礎(chǔ)教材選的不好)。我第一次接觸這一個api是在自己在嘗試的完成自己的課程設(shè)計(jì)項(xiàng)目時,在項(xiàng)目中使用了**ListView**展示一系列的數(shù)據(jù),當(dāng)時的數(shù)據(jù)量是比較的大,同時每一個listItem中的view也是比較的復(fù)雜,不僅有頭像,有用戶名,有標(biāo)題,有內(nèi)容,甚至是有圖片等等。
復(fù)雜的view的創(chuàng)建是會比較消耗機(jī)器的性能的,大量復(fù)雜的view就不用說了。因此我便在尋找方法優(yōu)化list的時候,接觸了setTag().在接觸Android開發(fā)以來,setTag()使用的最多的場景基本就是ListView,GridView,RecycleView,ViewPage,Gallery啊等等一系列類似用于展示大量重復(fù)的View的控件上。*因?yàn)檫@些控件的數(shù)據(jù)量一般會比較多,例如在夜夜項(xiàng)目中照片瀑布流中,一頁就是30張照片,加載十幾頁就是幾百張的圖片,如果不對資源加以回收的話,即使是劉威的一加3有6G內(nèi)存也都不夠用~*
因此,這一些控件基本都會對視圖判斷是否在可視的范圍,從而決定回不回收資源。**那么,問題就來了,當(dāng)被回收的view再一次出現(xiàn)在世人的眼前的時候,機(jī)器是不是需要重新綁定數(shù)據(jù),重新加載資源,重新繪制view?**問題的答案是肯定的,**當(dāng)然要!**(都已經(jīng)被回收了)那么明明已經(jīng)使用過的view再來一次也要重新開始繪制,那樣不是一直在重復(fù)同樣的動作?**特別是在一些列表或是網(wǎng)格的視圖中,明明每一個item都是長得一樣的,也是要重復(fù)創(chuàng)建?**同樣的事,重復(fù)的做,那就是在無謂的消耗機(jī)器性能了。**因此,我們要做的是讓同樣的事,只做一次就好!**
通過觀察,我們可以發(fā)現(xiàn),其實(shí)無論是ListView,GridView,RecycleView,ViewPage,還是Gallery,它們的使用都是離不開adapter,每一個子item的創(chuàng)建也是在adapter中的getView()中完成的,因此,我們**要開刀的就是adapter的getView()**.
在夜夜項(xiàng)目中的經(jīng)理列表,如下:

每一個itemView的布局都是一樣的,都包括了經(jīng)理頭像,名字,常去酒吧,性別,熱度,駐場,以及三張小的現(xiàn)場圖片。那么,該經(jīng)理listView的adapter中g(shù)etView()最正常的寫法如下:

其實(shí),在itemView相同的情況下,每一次創(chuàng)建itemView的時候都要重復(fù)的去綁定控件,須知,項(xiàng)目中R文件中的id可是非常very多的,這樣重復(fù)的findViewById是很消耗性能的,特別在控件還很多,一個list中的itemView也很多的情況下。那么,我們就要對綁定控件這一部分進(jìn)行優(yōu)化。
首先我們通過查詢setTag()的源碼就可以知道

setTag()是把Object對象作為參數(shù)對view進(jìn)行存儲的。也就是說,我們要把一個itemView中的控件抽取成一個Object,在此,我們創(chuàng)建了一個ViewHolder

然后修改getView()

在第一次創(chuàng)建itemView的時候,完成對控件的綁定,同時吧控件作為一個object--holder,把它通過setTag()存到itemView中,再第二次使用的時候就可以通過getTag()把holder取出來直接使用,也就是說,在list中itemView相同的情況下,我們只進(jìn)行了一次的控件資源綁定。是不是就省了很多?
**這樣的方式是適合用所有類似的控件的。包括上文提及的GridView,RecycleView,ViewPage,Gallery等,具體可以自己發(fā)揮**
### 那么,問題又來了!
在夜夜項(xiàng)目中開發(fā)在線聊天IM的時候,**聊天界面的消息也是由listView實(shí)現(xiàn)的,但是,ItemView長得不一樣啊???itemView有文本消息的,有圖片消息的,也有分享的名片、酒水套餐等,一個ViewHolder根本hold不住了喂!有可能上一次創(chuàng)建的文本消息itemView,這一次卻是要圖片消息的itemView了!**
其實(shí),這個問題根本**不用擔(dān)心!!!**我們翻一翻源碼又發(fā)現(xiàn),還有這個東西:setTag(key,object)

也就說,其實(shí)一個view中是可以setTag多個object的,我們只需要在setTag的時候指定key,只有再通過getTag(key)就可以取出相對應(yīng)的object了,界面再多類型的itemView,再多不同的holder也不怕了呢~
那么我為什么又要拿出來單獨(dú)說呢?因?yàn)?*這里面有坑!**
假如你這樣子使用:> `converView.setTag("text",textHolder);`
`converView.setTag("pic",picHolder);`
`converView.setTag(100,shareHolder);`
>
那么,恭喜你,你的項(xiàng)目要開始Crash了,開始拋出IllegalArgumentException的問題了~因?yàn)樵赟DK中有這樣子說過:>*“ 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必須是唯一的!!!**
那么我們要怎么實(shí)現(xiàn)唯一的key呢?其實(shí)我們可以把key定義在資源文件中,再由編譯器生成對應(yīng)的,唯一的id!因此我們可以這樣寫在項(xiàng)目的資源res/values/string.xml中:

然后直接:`converView.setTag(R.id.tag_text,textHolder);`
就可以了,取值的時候:`textHolder = converView.getTag(R.id.tag_text);`
然后,你就可以愉快的擼代碼啦~
###### 至此,全文基本完!
*edit by: 陳育生*
如果這篇文章又幫到你的話,請點(diǎn)一下‘喜歡’,我會更努力的創(chuàng)作的
總結(jié)
以上是生活随笔為你收集整理的android listview settag,Android View中setTag的二三事的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android重点笔记,安卓listvi
- 下一篇: Windows中鼠标滚轮乱跳的解决方法