Android: visible ListView images flicker when adding data to ArrayAdapter

谁说我不能喝 提交于 2019-12-04 04:12:51

The reason for this flicker is that, in listview list items are reused. When re-used, the imageviews in the list item retains the old image reference which is displayed first. Later on once new image is downloaded, it starts to show. this causes the flickering behavior. To avoid this flickering issue, always clear the old image reference from the imageview when it is getting reused.

In your case, add holder.image.setImageBitmap(null); after holder = (ViewHolder) convertView.getTag();

So, your getView() method will look like:

@Override public View getView(final int position, View convertView, ViewGroup parent) {

...

if (convertView == null) {
    LayoutInflater inflater = getLayoutInflater();
    convertView = inflater.inflate(viewResourceId, null);

    holder = new ViewHolder(convertView);
    convertView.setTag(holder);
} else {
    holder = (ViewHolder) convertView.getTag();
    holder.image.setImageBitmap(null)
}

...

return convertView;

}

Edit : I had similar issue, the images used to change rapidly. This happens because

getView() method of List adapter is called several times. every time getView() is called, you try to download and set the image on the row. By the time image is downloaded from the network, row in the list which requested for that image might have moved out of visible portion of screen but the adapter tries to reuse that row and this leads to setting previously requested image on new row at that position(previously requested row-position).

Try this approach in the adapter, set the requested URL on the ImageView with setTag :

if(item.get_referenceImage().length()!=0){
     //with view, hold the url. This is used to verify that right image is loaded on download completion  
     holder.refImageView.setTag(item.get_referenceImage());
     imageManager.loadImage(new MetaItem(item.get_referenceImage(), holder.refImageView));
 }else{
     //no image, set default
     Log.d(TAG, "No images found for the view setting default image");
     holder.refImageView.setTag(null); //this is req, otherwise image cache will retain previous image
     holder.refImageView.setImageResource(R.drawable.blank_96_1382x);
}

in cache, before loading the bitmap, check if right image is loaded:

 String url = (String) m_imageViewRef.get().getTag();
  if(url != null && url.compareTo(m_metaItem.m_url) == 0 ){ 
        m_metaItem.m_imageViewRef.get().setImageBitmap(result);
  }

PS: MetaItem is just a POJO to hold reference to imageView and image's URL

The solution is to not reload your image when it did not change.

In your adapters getView() do:

// schedule rendering:
final String path = ... (set path here);
if (holder.lastImageUrl == null || !holder.lastImageUrl.equals(path)
                || holder.headerImageView.getDrawable() == null) {
    // refresh image
    imageLoader.displayImage(imageUri, imageAware);
} else {
    // do nothing, image did not change and does not need to be updated
}

on success (add a ImageLoadingListener) you set holder.lastImageUrl = path, on fail and cancel you set holder.lastImageUrl to null so that it will reload next time.

You might be calling adapter.notifyDatasetChanged() which causes listview to reload its listitems. try not calling adapter.notifyDatasetChanged() your listview should automatically update when you scroll. but this can cause ArrayIndexOutOfBounds exception while scrolling.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!