最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android中ListView異步加載圖片錯(cuò)位、重復(fù)、閃爍問題分析及解決方案

 更新時(shí)間:2015年08月20日 11:48:46   作者:shineflowers  
在Android所有系統(tǒng)自帶的控件當(dāng)中,ListView這個(gè)控件算是用法比較復(fù)雜的了,關(guān)鍵是用法復(fù)雜也就算了,它還經(jīng)常會(huì)出現(xiàn)一些稀奇古怪的問題,讓人非常頭疼,下面通過本篇文章給大家分享Android中ListView異步加載圖片錯(cuò)位、重復(fù)、閃爍問題分析及解決方案,需要朋友可以參考

Android ListView異步加載圖片錯(cuò)位、重復(fù)、閃爍分析以及解決方案,具體問題分析以及解決方案請(qǐng)看下文。

我們?cè)谑褂肔istView異步加載圖片的時(shí)候,在快速滑動(dòng)或者網(wǎng)絡(luò)不好的情況下,會(huì)出現(xiàn)圖片錯(cuò)位、重復(fù)、閃爍等問題,其實(shí)這些問題總結(jié)起來就是一個(gè)問題,我們需要對(duì)這些問題進(jìn)行ListView的優(yōu)化。

比如ListView上有100個(gè)Item,一屏只顯示10個(gè)Item,我們知道getView()中convertView是用來復(fù)用View對(duì)象的,因?yàn)橐粋€(gè)Item的對(duì)應(yīng)一個(gè)View對(duì)象,而ImageView控件就是View對(duì)象通過findViewById()獲得的,而我們?cè)趶?fù)用View對(duì)象時(shí),同時(shí)這個(gè)ImageView對(duì)象也被復(fù)用了。比如第11個(gè)Item的View復(fù)用了第1個(gè)Item View對(duì)象,那么ImageView就同時(shí)被復(fù)用了,所以當(dāng)圖片沒下載出來,這個(gè)ImageView(第11個(gè)Item)顯示的數(shù)據(jù)就是復(fù)用(第1個(gè)Item)的數(shù)據(jù)。

1:Item圖片顯示重復(fù)

這個(gè)顯示重復(fù)是指當(dāng)前行Item顯示了之前某行Item的圖片。

比如ListView滑動(dòng)到第2行會(huì)異步加載某個(gè)圖片,但是加載很慢,加載過程中ListView已經(jīng)滑動(dòng)到了第14行,且滑動(dòng)過程中該圖片加載結(jié)束。第2行已不在屏幕內(nèi),根據(jù)上面介紹的緩存原理,第2行的View對(duì)象可能被第14行復(fù)用,這樣我們看到的就是第14行顯示了本該屬于第2行的圖片,造成顯示重復(fù)。

2. Item圖片顯示錯(cuò)亂

這個(gè)顯示錯(cuò)亂是指某行Item顯示了不屬于該行Item的圖片。

跟上面的原因一樣。

3. Item圖片顯示閃爍

上面介紹的另外一種情況,如果第14行圖片又很快加載結(jié)束,所以我們看到第14行先顯示了復(fù)用的第2行的圖片,立馬又顯示了自己的圖片進(jìn)行覆蓋造成閃爍錯(cuò)亂。

解決方案:

通過上面的分析我們知道了出現(xiàn)錯(cuò)亂的原因是異步加載及對(duì)象被復(fù)用造成的,如果每次getView能給對(duì)象一個(gè)標(biāo)識(shí),在異步加載完成時(shí)比較標(biāo)識(shí)與當(dāng)前行Item的標(biāo)識(shí)是否一致,一致則顯示,否則不做處理即可。

原理:首先給ImageView設(shè)置一個(gè)Tag,這個(gè)Tag中設(shè)置的是圖片的url,然后在加載的時(shí)候取得這個(gè)url和要加載那position中的url對(duì)比,如果不相同就加載,相同就是復(fù)用以前的就不加載了。

Android在ListView顯示圖片(重復(fù)錯(cuò)亂閃爍問題)

1、原因分析

ListView item緩存機(jī)制:

為了使得性能更優(yōu),ListView會(huì)緩存行item(某行對(duì)應(yīng)的View)。

ListView通過adapter的getView函數(shù)獲得每行的item。

滑動(dòng)過程中

a. 如果某行item已經(jīng)滑出屏幕,若該item不在緩存內(nèi),則put進(jìn)緩存,否則更新緩存;

b. 獲取滑入屏幕的行item之前會(huì)先判斷緩存中是否有可用的item,如果有,做為convertView參數(shù)傳遞給adapter的getView。

這樣,如下的getView寫法就可以充分利用緩存大大提升ListView的性能。即便上萬個(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í)也會(huì)造成另外一些問題:

a. 行item圖片顯示重復(fù)

這個(gè)顯示重復(fù)是指當(dāng)前行item顯示了之前某行item的圖片。

比如ListView滑動(dòng)到第2行會(huì)異步加載某個(gè)圖片,但是加載很慢,加載過程中l(wèi)istView已經(jīng)滑動(dòng)到了第14行,且滑動(dòng)過程中該圖片加載結(jié)束,

第2行已不在屏幕內(nèi),根據(jù)上面介紹的緩存原理,第2行的view可能被第14行復(fù)用,這樣我們看到的就是第14行顯示了本該屬于第2行的圖片,

造成顯示重復(fù)。

b. 行item圖片顯示錯(cuò)亂

這個(gè)顯示錯(cuò)亂是指某行item顯示了不屬于該行item的圖片。

比如ListView滑動(dòng)到第2行會(huì)異步加載某個(gè)圖片,但是加載很慢,加載過程中l(wèi)istView已經(jīng)滑動(dòng)到了第14行,第2行已不在屏幕內(nèi),根據(jù)上面介紹的緩存原理,第2行的view可能被第14行復(fù)用,第14行顯示了第2行的View,這時(shí)之前的圖片加載結(jié)束,就會(huì)顯示在第14行,造成錯(cuò)亂。

c. 行item圖片顯示閃爍

上面b的情況,第14行圖片又很快加載結(jié)束,所以我們看到第14行先顯示了第2行的圖片,立馬又顯示了自己的圖片進(jìn)行覆蓋造成閃爍錯(cuò)亂。

2、解決方法

通過上面的分析我們知道了出現(xiàn)錯(cuò)亂的原因是異步加載及對(duì)象被復(fù)用造成的,如果每次getView能給對(duì)象一個(gè)標(biāo)識(shí),在異步加載完成時(shí)比較標(biāo)識(shí)與當(dāng)前行item的標(biāo)識(shí)是否一致,一致則顯示,否則不做處理即可。

andbase中的實(shí)現(xiàn)代碼:

/**
  * 顯示這個(gè)圖片,解決了列表問題.
  * 列表問題:滑動(dòng)過程中,getView的imageView會(huì)重復(fù)利用,導(dǎo)致圖片會(huì)串位
  * @param imageView 顯得的View
  * @param url the url
  * @return
  */
  public void display( final ImageView imageView,String url) {
   if (AbStrUtil.isEmpty(url)){
    if (noImage != null ){
     if (loadingView != null ){
      loadingView.setVisibility(View.INVISIBLE);
      imageView.setVisibility(View.VISIBLE);
     }
     imageView.setImageDrawable(noImage);
    }
    return ;
   }
   //設(shè)置下載項(xiàng)
   final AbImageDownloadItem item = new AbImageDownloadItem();
   //設(shè)置顯示的大小
   item.width = width;
   item.height = height;
   //設(shè)置為縮放
   item.type = type;
   item.imageUrl = url;
   final String cacheKey = AbImageCache
   .getCacheKey(item.imageUrl, item.width, item.height, item.type);
   item.bitmap = AbImageCache.getBitmapFromCache(cacheKey);
   //if(D) Log.d(TAG, "緩存中獲取的"+cacheKey+":"+item.bitmap);
   //設(shè)置標(biāo)記
   imageView.setTag(url);
   if (item.bitmap == null ){
    //先顯示加載中
    if (loadingView!= null ){
     loadingView.setVisibility(View.VISIBLE);
     imageView.setVisibility(View.INVISIBLE);
    } else if (loadingImage != null ){
     imageView.setImageDrawable(loadingImage);
    }
    //下載完成后更新界面
    item.setListener( new AbImageDownloadListener() {
     @Override
     public void update(Bitmap bitmap, String imageUrl) {
      //未設(shè)置加載中的圖片,并且設(shè)置了隱藏的View
      if (loadingView != null && imageUrl.equals(imageView.getTag())){
       loadingView.setVisibility(View.INVISIBLE);
       imageView.setVisibility(View.VISIBLE);
      }
      //要判斷這個(gè)imageView的url有變化,如果沒有變化才set,
      //有變化就取消,解決列表的重復(fù)利用View的問題
      if(bitmap!=null&& imageUrl.equals(imageView.getTag())){
       if (D) Log.d(TAG, "圖片下載,設(shè)置:" +imageUrl);
       imageView.setImageBitmap(bitmap);
      } else {
       if (errorImage != null && imageUrl.equals(imageView.getTag())){
        imageView.setImageDrawable(errorImage);
       }
      }
     }
    });
    if (D) Log.d(TAG, "圖片下載,執(zhí)行:" +url);
    mAbImageDownloadPool.execute(item);
   } else {
    if (loadingView != null ){
     loadingView.setVisibility(View.INVISIBLE);
     imageView.setVisibility(View.VISIBLE);
    }
    imageView.setImageBitmap(item.bitmap);
   }
  }

以上內(nèi)容就是Android中ListView異步加載圖片錯(cuò)位、重復(fù)、閃爍問題分析及解決方案,希望對(duì)大家今后的工作和學(xué)習(xí)有所幫助。

相關(guān)文章

最新評(píng)論

凌云县| 北票市| 土默特右旗| 土默特左旗| 贵南县| 运城市| 吴桥县| 四平市| 宁波市| 郸城县| 海晏县| 特克斯县| 佛学| 八宿县| 陇川县| 通城县| 九龙城区| 福鼎市| 闸北区| 呼和浩特市| 鹤山市| 肇州县| 延安市| 米林县| 沈丘县| 策勒县| 阳新县| 馆陶县| 达州市| 康平县| 罗山县| 北安市| 宜都市| 罗平县| 涿州市| 烟台市| 都匀市| 遵化市| 仪征市| 荆门市| 贵港市|