2

I am trying to download images into a list view from URL's. When I scroll or while the list is populating the images flicker and are not on the right row..

here is my adapter code:

public class RecipesAdapter extends ArrayAdapter<XmlDataCollected> {
    // View lookup cache
    private static class ViewHolder {
        static ImageView img;
        TextView name;
        TextView info;
        ImageDownloader controller;
    }

    public RecipesAdapter(Context context, List<XmlDataCollected> recipes) {
        super(context, R.layout.fragment_search_result, recipes);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Get the data item for this position
        XmlDataCollected recipe = getItem(position);
        // Check if an existing view is being reused, otherwise inflate the view
        ViewHolder viewHolder; // view lookup cache stored in tag
        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.fragment_search_result, parent, false);
            viewHolder.name = (TextView) convertView.findViewById(R.id.label);
            viewHolder.info = (TextView) convertView.findViewById(R.id.info);
            ViewHolder.img = (ImageView) convertView.findViewById(R.id.icon);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
            viewHolder.img.setImageBitmap(null);
        }

        if (viewHolder.controller != null) {
            viewHolder.controller.cancel(false);
        }

        viewHolder.controller = new ImageDownloader(viewHolder.img);

        if (viewHolder.controller != null) {
            viewHolder.controller.execute(recipe.getImgUrl());
        }

        // Populate the data into the template view using the data object
        viewHolder.name.setText(recipe.getRecipeName());
        if(recipe.getType() != null) {
            viewHolder.info.setText(recipe.getType());
        }
        else {
            viewHolder.info.setText("Unknown category");
        }

        //new ImageDownloader(viewHolder.img).execute(recipe.getImgUrl());
        // Return the completed view to render on screen
        return convertView;
    }

    public class ImageDownloader extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public ImageDownloader(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            String url = urls[0];
            Bitmap mIcon = null;
            try {
                InputStream in = new java.net.URL(url).openStream();
                mIcon = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                Log.e("Error", e.getMessage());
            }
            return mIcon;

        }

        protected void onPostExecute(Bitmap result) {
            if(result != null) {
                bmImage.setImageBitmap(result);
            }
            else{
                bmImage.setImageResource(R.drawable.ic_launcher);
            }
        }
    }
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Max Helskens
  • 121
  • 1
  • 11
  • There are a few libraries to download a cache images from url like https://github.com/mcxiaoke/android-volley or http://square.github.io/picasso/. These will help you write less code and work much better. But I think you still need keep track of requests and stop downloading images for rows that are out of view. – Gent Ahmeti May 19 '15 at 08:25

3 Answers3

1

I had this problem too. In your getView() method add the following code:

if (viewHolder.controller != null) {
    viewHolder.controller.cancel(false);
}

viewHolder.controller = new ImageDownloader(viewHolder.img);

if (viewHolder.controller != null) {
    viewHolder.controller.execute(recipe.getImgUrl());
}
PatrickMA
  • 887
  • 9
  • 23
0

in your Listview xml
add this

android:cacheColorHint="#00000000"

or by code

 listView.setCacheColorHint(Color.TRANSPARENT);

and also remove

viewHolder.img.setImageBitmap(null);

from your else condition

Jeffy Lazar
  • 1,903
  • 13
  • 20
0

Other then the above suggestions, I have some other suggestions as well which might help.

You have to make your getView() method more optimized, since it is getting called for every row which enters to the visible area. Changing if/else conditions to method calls may help as well.

First of all I recommend you to look at this site:

http://leftshift.io/6-ways-to-make-your-lists-scroll-faster-than-the-wind

Changing the listview's height to match parent from wrap content also makes a huge difference for optimization, if you are using wrap_content. You can try making it 0dp as well. It creates the same result.

Check out this thread for "match_parent" optimization, if you need additional information.

Why is 0dp considered a performance enhancement?

Community
  • 1
  • 1
Oguz Ozcan
  • 1,694
  • 19
  • 26