最新內容建議直接訪問原文:Android ListView滑動過程當中圖片顯示重複錯亂閃爍問題解決java
主要分析Android ListView滾動過程當中圖片顯示重複、錯亂、閃爍的緣由及解決方法,順帶說起ListView的緩存機制。
一、緣由分析
ListView item緩存機制:爲了使得性能更優,ListView會緩存行item(某行對應的View)。ListView經過adapter的getView函數得到每行的item。滑動過程當中,android
a. 若是某行item已經滑出屏幕,若該item不在緩存內,則put進緩存,不然更新緩存;
b. 獲取滑入屏幕的行item以前會先判斷緩存中是否有可用的item,若是有,作爲convertView參數傳遞給adapter的getView。
更具體可見源代碼ListView.obtainView。git
這樣,以下的getView寫法就能夠充分利用緩存大大提高ListView的性能。即使上萬個行item,最多inflate的次數爲n,n爲一屏最多顯示ListView 行item的個數。github
a. 行item圖片顯示重複
這個顯示重複是指當前行item顯示了以前某行item的圖片。
好比ListView滑動到第2行會異步加載某個圖片,可是加載很慢,加載過程當中listView已經滑動到了第14行,且滑動過程當中該圖片加載結束,第2行已不在屏幕內,根據上面介紹的緩存原理,第2行的view可能被第14行復用,這樣咱們看到的就是第14行顯示了本該屬於第2行的圖片,形成顯示重複。緩存
b. 行item圖片顯示錯亂
這個顯示錯亂是指某行item顯示了不屬於該行item的圖片。
好比ListView滑動到第2行會異步加載某個圖片,可是加載很慢,加載過程當中listView已經滑動到了第14行,第2行已不在屏幕內,根據上面介紹的緩存原理,第2行的view可能被第14行復用,第14行顯示了第2行的View,這時以前的圖片加載結束,就會顯示在第14行,形成錯亂。網絡
c. 行item圖片顯示閃爍
上面b的狀況,第14行圖片又很快加載結束,因此咱們看到第14行先顯示了第2行的圖片,立馬又顯示了本身的圖片進行覆蓋形成閃爍錯亂。app
二、解決方法
經過上面的分析咱們知道了出現錯亂的緣由是異步加載及對象被複用形成的,若是每次getView能給對象一個標識,在異步加載完成時比較標識與當前行item的標識是否一致,一致則顯示,不然不作處理便可。
下面以使用ImageCache爲ListView提供圖片獲取緩存爲例,ListView中強烈推薦使用ImageCache。
首先在listview adapter的getView中添加異步
@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(); } …… // add tag for image, to compare it when image loaded finish imageView.setTag(imageUrl); // if not in cache, restore default if (!Cache.ICON_CACHE.get(imageUrl, imageView)) { imageView.setImageDrawable(null); } }
其中setTag表示設置標識,方便下面進行標誌比對ide
if (!Cache.ICON_CACHE.get(imageUrl, imageView))
Cache.ICON_CACHE爲ImageCache的實例,表示若是不在緩存內則設置drawable爲null(固然你能夠能夠設置爲你本身的默認資源),防止顯示了以前某個行item的圖片,解決了a. 行item圖片顯示重複問題。
在ImageCache的OnImageCallbackListener的onImageLoaded函數中添加
public void onImageLoaded(String imageUrl, Drawable imageDrawable, View view, boolean isInCache) { // 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();取得以前設置的tag,而後和當前的url進行比較,若是相等則顯示,解決了b. 行item圖片顯示錯亂,c. 行item圖片顯示錯亂的兩個問題。其中ObjectUtils可見ObjectUtils@Github.
其餘異步加載過程解決原理相似。
你可能還感興趣: