Retell data in listview format while fast scrolling down

I have this adapter which I download with data from the internet. It displays the wrong images for a second of a second before displaying the correct one if I quickly scroll down. However, the relevant text next to the images does not. This is more obvious when it downloads even more data on the fly. Please help me debug this. This is what the list looks like:

The listview

The categoryAdapter attribute is initialized with a list of data containing only text view data. When categoryAdapter getView () is called, it loads the image from the URL via asynthesis. The OnScrollListener loads 12 more articles (again just text) when the bottom of the list is reached. Here is getView (). Note that I thought the issue with the old views was related to the issue, so I tried to set the image to zero before changing the image images to the new image so that I don't see the old one. This worked to not see the error if I scroll quickly, but not if I quickly scroll down. What could be the problem?

class CategoryAdapter extends BaseAdapter{...
@Override
public View getView(int i, View view, final ViewGroup viewGroup){
    // crate a new rowItem object here
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View row;

    if (view == null) row = inflater.inflate(R.layout.single_row, viewGroup, false);
    else row = view;

    // Get the description, image and title of the row item
    TextView title = (TextView) row.findViewById(R.id.textView);
    TextView description = (TextView) row.findViewById(R.id.textView2);
    ImageView image = (ImageView) row.findViewById(R.id.imageView);
    ProgressBar pb = (ProgressBar) row.findViewById(R.id.progressBarSingleRow);

    /* On getting view, set this to invisible until loaded. (issue before: old image seen
       before new image on fast scroll) Mostly fixed by this, but on fast scroll down, still
       shows a little */
    image.setImageDrawable(null);

    // Set the values of the rowItem
    SingleRow rowTemp = articles.get(i);
    title.setText(rowTemp.title);
    description.setText(rowTemp.description);

    String s = "null";
    if (rowTemp.image != null) s = "not null";
    Log.e("ImageLog", "Item " + Integer.toString(i) + ", is " + s);

    // Load image into row element
    if (rowTemp.image == null) {    // download
        // Prepare prepped row objects in single holder object for fetchCategoryImageTask
        AdapterObject holder = new AdapterObject();
        holder.title = title;
        holder.description = description;
        holder.image = image;
        holder.pb = pb;

        new FetchCategoryImageTask(rowTemp, holder).execute();
    }
    else {                          // set saved image
        // Cropping image to preserve aspect ratio
        image.setScaleType(ImageView.ScaleType.CENTER_CROP);
        image.setCropToPadding(true);
        image.setImageBitmap(rowTemp.image);
    }

    return row;
}

      

Just in case, here's a little fetchCategoryImageTask ()

@Override
protected void onPreExecute() {
    image.setVisibility(ImageView.INVISIBLE);
}

@Override
protected Bitmap doInBackground(Void... params) {
    return (sr.imageURL != null) ? downloadBitmap(sr.imageURL) : null;
}

@Override
protected void onPostExecute(final Bitmap b) {
    // imageView image
    // Preserve aspect ratio of image
    image.setScaleType(ImageView.ScaleType.CENTER_CROP);
    image.setCropToPadding(true);
    image.setImageBitmap(b);

    // Make image visible
    image.setVisibility(ImageView.VISIBLE);

    // Save image to SingleRow object for categoryAdapter getView()
    sr.image = b;
}

      

+3


source to share


2 answers


This answer is from the comments, so I'll post it here. I'm going to use the viewHolder pattern to avoid looking at the views every time I get images of rows and caches with LRU cache. Here are the reference links: ViewHolder , Bitmap Caching .



0


source


What's going on here is that ListViews are reusing views. Therefore, it reuses the view that the image already has. I recommend you to use Volley library or ImageLoader library to solve this problem, it is easy to determine the placeholder displayed during image loading.

So, instead of using Asynctask, use the following code:



private void showImage(View view, String imageUrl) {
        DisplayImageOptions options = new DisplayImageOptions.Builder()//
                .showImageOnFail(R.drawable.image_placeholder) 
                .showImageOnLoading(R.drawable.image_placeholder) 
                .showImageForEmptyUri(R.drawable.image_placeholder) 
                .cacheInMemory(true) 
                .cacheOnDisk(true) 
                .build();
        ImageLoader.getInstance().displayImage(imageUrl, imageViewType, options);
    }

      

Universal Image Loader Library: https://github.com/nostra13/Android-Universal-Image-Loader

+1


source







All Articles