Android Listview 滑動(dòng)過(guò)程中提示圖片重復(fù)錯(cuò)亂的原因及解決方法
主要分析Android中Listview滾動(dòng)過(guò)程造成的圖片顯示重復(fù)、錯(cuò)亂、閃爍的原因及解決方法,順便跟進(jìn)Listview的緩存機(jī)制。
1、原因分析
Listview item 緩存機(jī)制:為了使得性能更優(yōu),Listview會(huì)緩存行item(某行對(duì)應(yīng)的view)。listview通過(guò)adapter的getview函數(shù)獲得每行的item?;瑒?dòng)過(guò)程中,
a、如果某行item已經(jīng)劃出屏幕,若該item不在緩存內(nèi),則put進(jìn)緩存,否則更新緩存;
b、獲取滑入屏幕的行item之前會(huì)先判斷緩存中是否有可用的item,如果有,作為convertview參數(shù)傳遞給adapter的getview。
這樣的話如下的getview寫法就可以充分利用緩存大大提升listview的性能。即便上萬(wàn)個(gè)行item,最多inflate的次數(shù)為n,n為一屏最多顯示listview行item的個(gè)數(shù)。
@Override public View getView(int position,View convertView,ViewGroup parent){ ViewHolder holder; if(convertView == null){ convertView = inflater.inflate(R.layout.list_item,null); holder = new ViewHolder(); ....convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } }
這樣提升了性能,但同時(shí)造成了一些問(wèn)題。
a、行item圖片顯示重復(fù)
這個(gè)顯示重復(fù)是指當(dāng)前行item顯示了之前某行item的圖片
比如listview滑動(dòng)到第二行會(huì)異步加載某個(gè)圖片,但是加載很慢,加載過(guò)程中l(wèi)istview已經(jīng)加載到15行,且滑動(dòng)過(guò)程中該圖片加載結(jié)束,第二行 已經(jīng)不再屏幕內(nèi),根據(jù)上面介紹的緩存原理,第二行的view可能被第14行服用,這樣我們看到的就是14行顯示了本該屬于第二行的圖片,造成重復(fù)。
b、行item圖片顯示錯(cuò)亂
這個(gè)顯示錯(cuò)亂是指某行item顯示了不屬于該行item的圖片。
比如listview滑動(dòng)到第二行會(huì)異步加載某個(gè)圖片,但是加載很慢,加載過(guò)程中l(wèi)istview已經(jīng)滑動(dòng)到14行,第二行已經(jīng)不再屏幕內(nèi),根據(jù)上面介紹 的緩存原理,第二行的view可能被第14行的復(fù)用,第十四行顯示了第二行的view這時(shí)之前的圖片加載結(jié)束,就會(huì)顯示在第14行,造成混亂。
c、行item圖品顯示閃爍
上面b情況,14行圖片又很快加載結(jié)束,所以我們看到第14行先顯示了第二行的圖片,馬上又顯示了自己的圖片進(jìn)行覆蓋造成的閃爍錯(cuò)亂。
2、解決方法
通過(guò)上面的分析我們知道了出現(xiàn)錯(cuò)亂的原因是異步加載及對(duì)象被復(fù)用造成的,如果每次getview能給對(duì)象一個(gè)標(biāo)識(shí),在異步加載完成時(shí)比較標(biāo)識(shí)與當(dāng)前的item的標(biāo)識(shí)是否是一致的,一致的則顯示,否則不做處理即可。
代碼中加上
@Override public View getView(int position,View convertView,ViewGroup parent){ ViewHolder holder; if(convertView == null){ convertView = inflater.inflate(R.layout.list_item,null); holder = new ViewHolder(); ....convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } 。。。。。 imageview.setTag(imageurl); if(!cache.icon_catch.get(imageurl,imageview){ imageview.setimageDrawable(null); } }
其中setTag表示設(shè)置標(biāo)識(shí),方便下面進(jìn)行標(biāo)志比對(duì)
if ( ! Cache . ICON_CACHE . get ( imageUrl , imageView ) )
Cache.ICON_CACHE為ImageCache的實(shí)例,表示如果不在緩存內(nèi)則設(shè)置drawable為null(當(dāng)然你可以可以設(shè)置為你自己的默認(rèn)資源),防止顯示了之前某個(gè)行item的圖片,解決了a. 行item圖片顯示重復(fù)問(wèn)題。
在ImageCache的OnImageCallbackListener的onImageLoaded函數(shù)中添加
Java
public void onImageLoaded ( String imageUrl , Drawable imageDrawable , View view , booleanisInCache ) { // can be another view child, like textView and so on if ( view != null && imageDrawable != null ) { ImageView imageView = ( ImageView ) view ; // add tag judge, avoid listView cache and so on String imageUrlTag = ( String ) imageView . getTag ( ) ; if ( ObjectUtils . isEquals ( imageUrlTag , imageUrl ) ) { imageView . setImageDrawable ( imageDrawable ) ; } } } ;
在上面用String imageUrlTag = (String)imageView.getTag();取得之前設(shè)置的tag,然后和當(dāng)前的url進(jìn)行比較,如果相等則顯示,解決了b. 行item圖片顯示錯(cuò)亂,c. 行item圖片顯示錯(cuò)亂的兩個(gè)問(wèn)題。其中ObjectUtils可見(jiàn)ObjectUtils@Github .
其他異步加載過(guò)程解決原理類似。
以上所述是小編給大家介紹的Android Listview 滑動(dòng)過(guò)程中提示圖片重復(fù)錯(cuò)亂的原因及解決方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android下拉刷新ListView——RTPullListView(demo)
- android開(kāi)發(fā)教程之實(shí)現(xiàn)listview下拉刷新和上拉刷新效果
- Android實(shí)現(xiàn)上拉加載更多以及下拉刷新功能(ListView)
- android下拉刷新ListView的介紹和實(shí)現(xiàn)代碼
- Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能
- Android ListView下拉刷新上拉自動(dòng)加載更多DEMO示例
- Android中ListView異步加載圖片錯(cuò)位、重復(fù)、閃爍問(wèn)題分析及解決方案
- Android實(shí)現(xiàn)Listview異步加載網(wǎng)絡(luò)圖片并動(dòng)態(tài)更新的方法
- 安卓(Android)ListView 顯示圖片文字
- Android ListView實(shí)現(xiàn)下拉頂部圖片變大效果
相關(guān)文章
Android自定義FloatingActionButton滑動(dòng)行為只隱藏不出現(xiàn)的問(wèn)題小結(jié)
這篇文章主要介紹了Android自定義FloatingActionButton滑動(dòng)行為只隱藏不出現(xiàn)的問(wèn)題小結(jié),需要的朋友可以參考下2017-01-01android studio的Handler簡(jiǎn)單實(shí)例代碼
今天通過(guò)實(shí)例代碼給大家介紹android studio的Handler簡(jiǎn)單用法,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-10-10Android 判斷所有字段是否已經(jīng)輸入的實(shí)例
今天小編就為大家分享一篇Android 判斷所有字段是否已經(jīng)輸入的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03Android如何實(shí)現(xiàn)掃描和生成二維碼
這篇文章主要為大家詳細(xì)介紹了Android如何實(shí)現(xiàn)掃描和生成二維碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05Android手機(jī)信號(hào)強(qiáng)度檢測(cè)詳細(xì)介紹
這篇文章主要介紹了Android手機(jī)信號(hào)強(qiáng)度檢測(cè)的相關(guān)資料,android定義了2種信號(hào)單位:dBm和asu。具體兩種的關(guān)系本文給大家介紹非常詳細(xì),需要的朋友可以參考下2016-11-11Android中ListView + CheckBox實(shí)現(xiàn)單選、多選效果
這篇文章主要介紹了Android中ListView + CheckBox實(shí)現(xiàn)單選、多選效果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02Android實(shí)現(xiàn)登錄功能demo示例
這篇文章主要介紹了Android實(shí)現(xiàn)登錄功能demo示例,涉及登錄信息操作、界面布局、登錄邏輯判斷等相關(guān)操作技巧,需要的朋友可以參考下2016-07-07Android開(kāi)發(fā)之利用Intent實(shí)現(xiàn)數(shù)據(jù)傳遞的方法
這篇文章主要介紹了Android開(kāi)發(fā)之利用Intent實(shí)現(xiàn)數(shù)據(jù)傳遞的方法,實(shí)例分析了Intent傳遞數(shù)據(jù)的原理與相關(guān)使用技巧,需要的朋友可以參考下2016-03-03Android協(xié)程作用域與序列發(fā)生器限制介紹梳理
協(xié)程的作用是什么?協(xié)程是一種輕量級(jí)的線程,解決異步編程的復(fù)雜性,異步的代碼使用協(xié)程可以用順序進(jìn)行表達(dá),文中通過(guò)示例代碼介紹詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-08-08