當(dāng)前位置:
首頁 >
Listview性能优化
發(fā)布時(shí)間:2025/7/14
57
豆豆
生活随笔
收集整理的這篇文章主要介紹了
Listview性能优化
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
也許你會(huì)在getView中這樣做
?
如果你在Adapter初始化的時(shí)候創(chuàng)建一個(gè)Listener public MyAdapter () {myListener = new View.OnClickListener() {@overridepublic void onClick(View v) {v.getTag()v.getId()//balabalabala... }}); }
?
通過傳入的View v這個(gè)參數(shù)判斷是哪一個(gè)button被點(diǎn)擊,這樣,無論View如何創(chuàng)建,你只創(chuàng)建了1個(gè)Listener對(duì)象這只是一個(gè)小細(xì)節(jié),優(yōu)化的方式要綜合使用,才會(huì)事半功倍
------------------7月24日更-----------------
v.getTag() 這個(gè)tag本不是用來存數(shù)據(jù)的,通俗點(diǎn)講它和view 的Id是同一個(gè)東西,只不過tag的類型是Object。實(shí)際上在tag中存儲(chǔ)數(shù)據(jù)是不符合規(guī)范的方式
但其實(shí)View類有兩種tag,
setTag(Object?tag) 方法將tag保存在一個(gè)成員變量中,findViewWithTag正是遍歷此tag
setTag(int key,?Object?tag) 方法是最終是調(diào)用View類中的setKeyedTag(int key, Object tag)
這是一個(gè)私有方法
他是用 SparseArray 實(shí)現(xiàn)的,我們可以把需要的東西存到這里面(其實(shí)觀察源碼可以發(fā)現(xiàn),系統(tǒng)很多時(shí)候都是這樣做的)
這里要注意一點(diǎn),參數(shù)key必須是唯一的,那么我們可以這樣做
那么需要先在res/values/strings.xml中添加
?
?
有人問,如果這樣寫,所有button只能通過id區(qū)分邏輯,無法傳入每個(gè)item的數(shù)據(jù)
我們可以將數(shù)據(jù)通過view 的tag帶進(jìn)來
1 public View getView(.....) { 2 .... 3 v.setTag(key, getItem(position)); 4 .... 5 } 然后在listener中通過v.getTag()將數(shù)據(jù)取出
-----------------------7月25日update-------------------
這里我有一個(gè)失誤
如果listener里面的邏輯與當(dāng)前的item有關(guān),那么其實(shí)并不只是創(chuàng)建了21個(gè)listener對(duì)象
1 public void getView (View convertView ,final int position ....) { 2 if (convertView == null) { 3 View v = LayoutInflater.from(mContext).inflate(...); 4 v.setOnclickListener(new View.OnClickListener () { 5 @override 6 public void onClick(View v) { 7 getItem(position); 8 } 9 }); 10 } else { 11 12 } 13 } 你看下,如果綁定數(shù)據(jù)在convertView為空的情況下確實(shí)只創(chuàng)建了有限個(gè)listener,
但是在這種情況下綁定上的數(shù)據(jù)只有View創(chuàng)建時(shí)的7個(gè),之后不為空的情況下沒有更換listener導(dǎo)致重用的view數(shù)據(jù)是新的,listener里面的position依然是過去創(chuàng)建view時(shí)的7個(gè)之一,不會(huì)變化(注意參數(shù)上的final)
若在else里面再重新setListener,view是有重用,listener被換成新的,并與新的position綁定,老的listener就會(huì)變成一個(gè)廢對(duì)象,等待gc回收,隨著list滾動(dòng),越來越多
關(guān)鍵是我們的業(yè)務(wù)與position這個(gè)參數(shù)有關(guān)
1.重用?convertView?
用以避免重復(fù)創(chuàng)建 View,重復(fù)創(chuàng)建 View 代價(jià)較大,而且如果重用 view 不改變寬高,重用View可以減少重新分配緩存造成的內(nèi)存頻繁分配/回收;
2. 避免在 getView 中有 重復(fù)調(diào)用的 findViewById
findViewById 的實(shí)現(xiàn)是遍歷,如果你定義的 View 越復(fù)雜代價(jià)越大。
Google 推薦的做法是用 ViewHolder,然后保存在 view 的 tag 中。現(xiàn)在 RecyclerView 也是強(qiáng)制使用 ViewHolder 了。
3. 設(shè)置 View (如 TextView#setText )之前先對(duì)比數(shù)據(jù)是否有改變
一般來說,【比較兩個(gè)數(shù)據(jù)的代價(jià)】遠(yuǎn)小于【 View 的重繪的代價(jià)】
4.?避免在 getView 函數(shù)中直接加載 Image 或做其他比較耗時(shí)的操作
加載本地 Image 需要載入內(nèi)存以及解析 Bitmap ,都是比較耗時(shí)的操作。
用戶快速滑動(dòng)列表時(shí),會(huì)大量調(diào)用 getView ,而 getView 是在主線程中被調(diào)用的。如果你在 getView 函數(shù)中直接加載 Image 或做其他耗時(shí)操作,就會(huì)造成滑動(dòng)比較卡。加載 ImageView 的解決方案就是開一個(gè)線程去把做這事。有很多第三庫可以做這事。
5. ListView 中元素避免半透明
半透明繪制需要大量乘法計(jì)算,在滑動(dòng)時(shí)不停重繪會(huì)造成大量的計(jì)算,在比較差的機(jī)子上會(huì)比較卡。在設(shè)計(jì)上能不半透明就不不半透明。實(shí)在要弄的話我個(gè)人是用個(gè)比較偷懶的方法,是在滑動(dòng)的時(shí)候把半透明設(shè)置成不透明,滑動(dòng)完再重新設(shè)置成半透明。
6. 盡量開啟硬件加速
硬件加速提升巨大,避免使用一些不支持的函數(shù)導(dǎo)致含淚關(guān)閉某個(gè)地方的硬件加速。
當(dāng)然這一條不只是對(duì) ListView。
7.用 ListView 威力加強(qiáng)版 -- RecyclerView
更多的新武將,更多的姿勢(shì),更規(guī)范的使用,更好用的動(dòng)畫,更加強(qiáng)大的變化 ? 轉(zhuǎn)載自知乎(http://www.zhihu.com/question/19703384)
總結(jié)
以上是生活随笔為你收集整理的Listview性能优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下一个简单守护进程的实现 (D
- 下一篇: PEP 0498 -- Literal