0

I have this CustomAdapter, to fill a list with my data. The problem is that the Imageview is downloaded and drawed a lot of times. Example:

I search to my server a list of videos:

(Video1) Title 1 Description 1

(Video2) Title 2 Description 2

(Video3) Title 3 Description 3

..

When this loads, the image from the Video1 loads, then on the same Imageview, the Video2Image load, and again for each video on the list, same times how videos are on the list. When I scroll the adapter, this download all the images again. There are some option to fix this, I dont understand this behaivour.

CustomAdapter.java

public class CustomAdapter extends ArrayAdapter<Video> {
    // declaring our ArrayList of items
    private ArrayList<Video> objects;

    public CustomAdapter(Context context, int textViewResourceId, ArrayList<Video> objects) {
        super(context, textViewResourceId, objects);
        this.objects = objects;
    }

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

        View v = convertView;

        if (v == null) {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.list_row, null);
        }

        Video i = objects.get(position);

        if (i != null) {

            TextView title = (TextView) v.findViewById(R.id.title);
            TextView description = (TextView) v.findViewById(R.id.description);
            ImageView imagen = (ImageView) v.findViewById(R.id.list_image);

            title.setText(i.getTitulo());
            description.setText(i.getDescripcion());

            //Creamos imagen descargada y la seteamos
            new DownloadImageTask(imagen).execute(i.getUrlimagen());
            BitmapDrawable drawable = (BitmapDrawable) imagen.getDrawable();
            Bitmap bitmap = drawable.getBitmap();
            imagen.setImageBitmap(bitmap);

            Log.i("Debug", "Creando una imagen para: " + i.getTitulo());

            v.setTag(R.id.id_url, i.getUrl().trim());//1.Url
            v.setTag(R.id.id_titulo,i.getTitulo().trim());//2.Título
            v.setTag(R.id.id_video,i.getId().trim());//3.ID

        }

        return v;

    }

    private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

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

        protected Bitmap doInBackground(String... urls) {
            String urldisplay = urls[0];
            Bitmap mIcon11 = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                BitmapFactory BitmapFactory = null;
                mIcon11 = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return mIcon11;
        }

        protected void onPostExecute(Bitmap result) {
            if(result!=null)
                bmImage.setImageBitmap(result);
        }
    }

    public ArrayList getValues(){
        return objects;
    }

}

Sorry my english.

Genaut
  • 1,810
  • 2
  • 29
  • 60

3 Answers3

1

I had this problem a while back. If you put a log in getView() you will see that it is called whenever you scroll past the end of the screen. This means the images are being downloaded many many times as you scroll.

To get around this you need to cache your bitmaps. Once you have a cache, every time you call getView, do a query to the cache FIRST to see if the image has already been downloaded THEN if it is not available, download it and add it to the cache.

This method is explained (with code) here on Android Developers. http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

Vidia
  • 471
  • 5
  • 17
1

I answer that before and I answer it again for you: do not re-invent the wheel!

Image download/caching is q pretty complex thing for reasons you're seeing now (and others such as memory management, cache management, etc), so just use a library that works.

Below is your code using Picasso (my favorite image download library for android)

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

    View v = convertView;

    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.list_row, null);
    }

    Video i = objects.get(position);

    if (i != null) {

        TextView title = (TextView) v.findViewById(R.id.title);
        TextView description = (TextView) v.findViewById(R.id.description);
        ImageView imagen = (ImageView) v.findViewById(R.id.list_image);

        title.setText(i.getTitulo());
        description.setText(i.getDescripcion());

        //Creamos imagen descargada y la seteamos
        Picasso
            .with(imagen.getContext())
            .load(i.getUrlimagen())
            .into(imagen);

        Log.i("Debug", "Creando una imagen para: " + i.getTitulo());

        v.setTag(R.id.id_url, i.getUrl().trim());//1.Url
        v.setTag(R.id.id_titulo,i.getTitulo().trim());//2.Título
        v.setTag(R.id.id_video,i.getId().trim());//3.ID

    }

    return v;

}

Done! That code takes care of threading, caching, cancellation.

ps.: You should read a bit more regaring adapter and the ViewHolder pattern, you're not doing it correctly.

Budius
  • 39,391
  • 16
  • 102
  • 144
0

Your getview is always creating a DownloadImageTask. You don't want to do that- you want to check to see if you already have it, and download a new one only if you don't.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127