Frage

I have used an AsyncTask class to download and load images in listview asynchronously. But I have facing a problem which is the images of each row in the listvew will change continuously. Can anyone tell how to solve this problem and set the images to the right row position after loading?

ImageDownloaderTask class (AsyncTask)

class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;

public ImageDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
}

@Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
        // params comes from the execute() call: params[0] is the url.
        return downloadBitmap(params[0]);
}

@Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
                bitmap = null;
        }

        if (imageViewReference != null) {
                ImageView imageView = imageViewReference.get();
                if (imageView != null) {

                        if (bitmap != null) {
                                imageView.setImageBitmap(bitmap);
                        } else {
                                imageView.setImageDrawable(imageView.getContext().getResources()
                                                .getDrawable(R.drawable.placeholder_gaan));
                        }
                }

        }
}

static Bitmap downloadBitmap(String url) {
        final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
        final HttpGet getRequest = new HttpGet(url);
        try {
                HttpResponse response = client.execute(getRequest);
                final int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != HttpStatus.SC_OK) {
                        Log.w("ImageDownloader", "Error " + statusCode
                                        + " while retrieving bitmap from " + url);
                        return null;
                }

                final HttpEntity entity = response.getEntity();
                if (entity != null) {
                        InputStream inputStream = null;
                        try {
                                inputStream = entity.getContent();
                                final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                                return bitmap;
                        } finally {
                                if (inputStream != null) {
                                        inputStream.close();
                                }
                                entity.consumeContent();
                        }
                }
        } catch (Exception e) {
                // Could provide a more explicit error message for IOException or
                // IllegalStateException
                getRequest.abort();
                Log.w("ImageDownloader", "Error while retrieving bitmap from " + url);
        } finally {
                if (client != null) {
                        client.close();
                }
        }
        return null;
    }
}

Adapter class

public class MenuAdapter extends ArrayAdapter<ItemRow> {

    Context context; 
    public MenuAdapter(Context context, int resourceId,
            List<ItemRow> items) {
        super(context, resourceId, items);
        this.context = context;
    }

    /*private view holder class*/
    private class ViewHolder {
        TextView txtTitle;
        TextView txtBengTitle;
        TextView txtArtist;
        TextView txtTotalSongs;
        ImageView thumbImage;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        ItemRow rowItem = getItem(position);

        LayoutInflater mInflater = (LayoutInflater) context
                .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item_row, null);
            holder = new ViewHolder();
            holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
            holder.txtBengTitle = (TextView) convertView.findViewById(R.id.bengaliTitle);
            holder.thumbImage = (ImageView) convertView.findViewById(R.id.thumbAlbum);
            holder.txtArtist = (TextView) convertView.findViewById(R.id.artist);
            holder.txtTotalSongs = (TextView) convertView.findViewById(R.id.totalSongs);
            convertView.setTag(holder);
        } else
            holder = (ViewHolder) convertView.getTag();

        holder.txtTitle.setText(rowItem.getTitle());
        holder.txtBengTitle.setText(rowItem.getBengaliTitle());
        holder.txtArtist.setText(rowItem.getArtist());
        holder.txtTotalSongs.setText(rowItem.getTotalSongs());
        String imageUrl = rowItem.getImage();
        if (holder.thumbImage != null) {
            new ImageDownloaderTask(holder.thumbImage).execute(imageUrl);
        }


        return convertView;
    }


}
War es hilfreich?

Lösung

Andere Tipps

you need a mechanism to know if the view hasn’t been recycled once you’re done with the async operation.

Try to implement this pattern to track item is visible or not

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

    ...

    holder.position = position;

    new ThumbnailTask(position, holder)
            .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);

    return convertView;
}

private static class ThumbnailTask extends AsyncTask {
    private int mPosition;
    private ViewHolder mHolder;

    public ThumbnailTask(int position, ViewHolder holder) {
        mPosition = position;
        mHolder = holder;
    }

    @Override
    protected Cursor doInBackground(Void... arg0) {
        // Download bitmap here
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (mHolder.position == mPosition) {
            mHolder.thumbnail.setImageBitmap(bitmap);
        }
    }
}

private static class ViewHolder {
    public ImageView thumbnail;
    public int position;
}

For good ref on ListView look at thisPerformance Tips for Android’s ListView

Finally, I have got a simple solution by using the following open source library which is very easy to use without using ImageDownloaderTask class.

Ion

I believe You are running into problems because of the order in which the download of images is getting complete. You need stop the download of previous image while scrolling the new one to view. Here is the helpful tutorial for this

http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

You should read "Handling concurrency" section of this.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top