主要分析Android中Listview滾動過程造成的圖片顯示重複、錯亂、閃爍的原因及解決方案,順便跟進Listview的緩衝機制。
1、原因分析
Listview item 緩衝機制:為了使得效能更優,Listview會緩衝行item(某行對應的view)。listview通過adapter的getview函數獲得每行的item。滑動過程中,
a、如果某行item已經划出螢幕,若該item不在緩衝內,則put進緩衝,否則更新緩衝;
b、擷取滑入螢幕的行item之前會先判斷緩衝中是否有可用的item,如果有,作為convertview參數傳遞給adapter的getview。
這樣的話如下的getview寫法就可以充分利用緩衝大大提升listview的效能。即便上萬個行item,最多inflate的次數為n,n為一屏最多顯示listview行item的個數。
@Overridepublic 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();}}
這樣提升了效能,但同時造成了一些問題。
a、行item圖片顯示重複
這個顯示重複是指當前行item顯示了之前某行item的圖片
比如listview滑動到第二行會非同步載入某個圖片,但是載入很慢,載入過程中listview已經載入到15行,且滑動過程中該圖片載入結束,第二行 已經不再螢幕內,根據上面介紹的緩衝原理,第二行的view可能被第14行服用,這樣我們看到的就是14行顯示了本該屬於第二行的圖片,造成重複。
b、行item圖片顯示錯亂
這個顯示錯亂是指某行item顯示了不屬於該行item的圖片。
比如listview滑動到第二行會非同步載入某個圖片,但是載入很慢,載入過程中listview已經滑動到14行,第二行已經不再螢幕內,根據上面介紹 的緩衝原理,第二行的view可能被第14行的複用,第十四行顯示了第二行的view這時之前的圖片載入結束,就會顯示在第14行,造成混亂。
c、行item圖品顯示閃爍
上面b情況,14行圖片又很快載入結束,所以我們看到第14行先顯示了第二行的圖片,馬上又顯示了自己的圖片進行覆蓋造成的閃爍錯亂。
2、解決方案
通過上面的分析我們知道了出現錯亂的原因是非同步載入及對象被複用造成的,如果每次getview能給對象一個標識,在非同步載入完成時比較標識與當前的item的標識是否是一致的,一致的則顯示,否則不做處理即可。
代碼中加上
@Overridepublic 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表示設定標識,方便下面進行標誌比對
if ( ! Cache . ICON_CACHE . get ( imageUrl , imageView ) )
Cache.ICON_CACHE為ImageCache的執行個體,表示如果不在緩衝內則設定drawable為null(當然你可以可以設定為你自己的預設資源),防止顯示了之前某個行item的圖片,解決了a. 行item圖片顯示重複問題。
在ImageCache的OnImageCallbackListener的onImageLoaded函數中添加
Java
public void onImageLoaded ( String imageUrl , Drawable imageDrawable , View view , booleanisInCache ) {// can be another view child, like textView and so onif ( view != null && imageDrawable != null ) {ImageView imageView = ( ImageView ) view ;// add tag judge, avoid listView cache and so onString imageUrlTag = ( String ) imageView . getTag ( ) ;if ( ObjectUtils . isEquals ( imageUrlTag , imageUrl ) ) {imageView . setImageDrawable ( imageDrawable ) ;}}} ;
在上面用String imageUrlTag = (String)imageView.getTag();取得之前設定的tag,然後和當前的url進行比較,如果相等則顯示,解決了b. 行item圖片顯示錯亂,c. 行item圖片顯示錯亂的兩個問題。其中ObjectUtils可見ObjectUtils@Github .
其他非同步載入過程解決原理類似。
以上所述是小編給大家介紹的Android Listview 滑動過程中提示圖片重複錯亂的原因及解決方案,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對雲棲社區網站的支援!