Search code examples
androidandroid-gridviewandroid-adapteruniversal-image-loader

How to prevent GridView vibration (loading images) every time I call notifyDataSetChanged()?


I display gridview with universal-image-loader,and each grid item include ImageView and LoadingLinearProgress , over time I need to update the LoadingLinearProgress(underLineProgress) setting percent value so receiving percent I call notifyDataSetChanged(); and the images of gridView vibrate every time when it notified (it calls loadImage every time)

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

    if (convertView == null) {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.my_library_grid_item, parent, false);
        holder.ivCover = (LinearLayout) convertView.findViewById(R.id.iv_cover);
        holder.underLineProgress = (LoadingLinearProgress) convertView.findViewById(R.id.underline_progress);
      convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    loadAndDisplayImage(fileName,holder.ivCover);
    holder.underLineProgress.setPercent(getItem(position).getPercent);
    String firstPageUrl = magazineList.get(position).getFirtPage();
    loadAndDisplayImage(firstPageUrl, holder.ivCover, holder.libraryBackground);
    return convertView;
}




 private void loadAndDisplayImage(String fileName, ImageView imageView) {


    imageLoader.displayImage(fileName, imageView, getStoringUILOptions(), new ImageLoadingListener() {
        @Override
        public void onLoadingStarted(String imageUri, View view) {

        }

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) {

        }

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
           }

        @Override
        public void onLoadingCancelled(String imageUri, View view) {

        }
    });

}

Solution

  • Try this way: add a variable to the ViewHolder class that will contain some information that is in the object you get with magazineList.get(position) (or getItem(position), depending on how your grid works). Before loading the images, check if the variable stored in the holder has the same value of the one that is in the current item. If it's different, it means the view is being recycled, otherwise it means that notifyDataSetChanged() has been called, in which case you won't call loadAndDisplayImage.
    If the view is being recycled, set the holder's variable's value to the one of the current item.

    Code example:

    public View getView(final int position, View convertView, ViewGroup parent) {
    
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.my_library_grid_item, parent, false);
            holder.ivCover = (LinearLayout) convertView.findViewById(R.id.iv_cover);
            holder.underLineProgress = (LoadingLinearProgress) convertView.findViewById(R.id.underline_progress);
            holder.currentMagazine = "NONE"; // to avoid checking for null every time
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
    
        holder.underLineProgress.setPercent(getItem(position).getPercent);
        // I don't know what the above line is for, so I put it here. I guess it's
        // the one you have to run every time
    
        if(holder.currentMagazine.equals(getItem(position).title))  {// for example
    
            loadAndDisplayImage(fileName, holder.ivCover);
            String firstPageUrl = magazineList.get(position).getFirtPage();
            loadAndDisplayImage(firstPageUrl, holder.ivCover, holder.libraryBackground);
    
            holder.currentMagazine = getItem(position).title;
        }
    
        return convertView;
    }
    
    private static class ViewHolder {
        String currentMagazine;
        ImageView ivCover;
        LoadingLinearProgress underLineProgress;
    }
    

    In case that there's the possibility for an item's image to change and you having to load the new one when notifyDataSetChanged() is called, you will have to come up with something to know if the image is the same as before or not and check for that too.

    Source: I'm doing this in my app too. I noticed the problem by reading your question, otherwise I would have kept leaving my images to reload every time, so thanks.