steve_patrick
steve_patrick

Reputation: 735

Lazy load of images on ListView with AsyncTask launched on the getView (adapter)

I have a ListView with items that have some text and one ImageView. I would like to use and AsyncTask in order to load the ImageView (lazy load). I know there are some libraries in order to do that. The problem is that is not possible to get the images just with a URL, like

imageLoader.displayImage(imageUri, imageView);

because I need to add some headers to the HTTP GET (authentication token). So inside the getView() of the adapter I have to launch an AsyncTask that will download the image as Bitmap and show it on the ImageView.

Is there any code example? I tried to pass the ImageView to the AsyncTask in the constructor of the AsyncTask, download the Bitmap and assign it to the ImageView on the onPostExecute, something like this:

public class LoadImageTask extends AsyncTask<String, Void, Bitmap>{

private ImageView mImage;
private Context mContext;
private String imageId;
private Throwable mThrown = null;

public LoadImageTask(ImageView ivImage, Context context) {
    mImage = ivImage;
    mContext = context;
}

@Override
protected Bitmap doInBackground(String... params) {
    imageId = params[0];

      // Build request and request token
      ....
          //Process the response
            try {

                HttpEntity entity = mHttpResponse.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedInputStream bis = new BufferedInputStream(inputStream);
                Bitmap bm = BitmapFactory.decodeStream(bis);
                bis.close();
                inputStream.close();
                return bm;
            } catch (IOException e) {
                mThrown = e;
                RestClient.consumeContent(mHttpResponse);
                return null;
            }

        }
        RestClient.consumeContent(mHttpResponse);
        return null;
}

@Override
protected void onPostExecute(Bitmap bm) {
    mImage.setImageBitmap(bm);
}

}

public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.news_item, null);
    TextView tvNewsTitle = (TextView) rowView.findViewById(R.id.tvNewsTitle);
    TextView tvUpdateDate = (TextView) rowView.findViewById(R.id.tvUpdateDate);
    ImageView ivImage = (ImageView) rowView.findViewById(R.id.ivNewsThumbnail);   

    News news = mNewsList.get(position);
    tvNewsTitle.setText(news.getTitle());
    tvUpdateDate.setText(news.getLastUpdate());
    new LoadImageTask(ivImage, mContext).execute(news.getImageThumbnail());
    return rowView;
}

But looks like it's always updating only the fist element of the ListView.

Is there any example code?

Upvotes: 0

Views: 4028

Answers (2)

Phil
Phil

Reputation: 36299

The droidQuery library has both a shorthand and longhand method for lazy-loading images. The shorthand method, like you suggest, does not allow the addition of headers:

$.with(myImageView).image(the_url);

The longhand, however does:

$.ajax(new AjaxOptions().url(the_url)
                        .type("GET")
                        .dataType("image")
                        .header("username", username)
                        .header("password", password)
                        .success(new Function() {
                            @Override
                            public void invoke($ d, Object... args) {
                                $.with(myImageView).image((Bitmap) args[0]);
                            }
                        }));

Upvotes: 0

Robert Rowntree
Robert Rowntree

Reputation: 6289

see git lazylist for the code....

Using the code to do what you ask...

OnClickInList OR in the Fragment that wraps the view with bitmaps u need...

  imgLoadr.DisplayImage(mMap.get("pic"), imgview);

above calls into branching code depends on ( bitmap in memCache Y/N, bitmap in local Files Y/N, bitmap avail across the Web via URL ).

You dont have to worry about the implementation for the branches above .Lib takes care of it for u.

DisplayImage(){}...
    if(bitmap!=null){
            imageView.setImageBitmap(bitmap);
        }
        else
        {   
            queuePhoto(url, imageView);
            imageView.setImageResource(stub_id);

Set your HTTP HEADERS in the runnable...

 public Bitmap getBitmap(String url)
    {

        File f=fileCache.getFile(url);
        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is=conn.getInputStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex){

get the project lazylist

In you

Upvotes: 1

Related Questions