Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to load internet images in gridview efficiently?

I am using following example to display internet images in my activity.

http://developer.android.com/resources/tutorials/views/hello-gridview.html

In custom image adapter I'm directly loading images from internet and assigning it to imageview.

Which shows images in gridview and every thing works fine but it is not efficient way.

When ever i scroll gridview it again and again loads images and thats why gridview scrolls very slow

Is there caching or some useful technique available to make it faster?

like image 585
UMAR-MOBITSOLUTIONS Avatar asked Nov 19 '10 14:11

UMAR-MOBITSOLUTIONS


1 Answers

Create a global and static method which returns a Bitmap. This method will take parameters: context,imageUrl, and imageName.

in the method:

  1. check if the file already exists in the cache. if it does, return the bitmap

        if(new File(context.getCacheDir(), imageName).exists())
            return BitmapFactory.decodeFile(new File(context.getCacheDir(), imageName).getPath());
    
  2. otherwise you must load the image from the web, and save it to the cache:

    image = BitmapFactory.decodeStream(HttpClient.fetchInputStream(imageUrl));
    
    
    
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(new File(context.getCacheDir(), imageName));
    }
    
    
    //this should never happen
    catch(FileNotFoundException e) {
        if(Constants.LOGGING)
            Log.e(TAG, e.toString(), e);
    }
    
    
    //if the file couldn't be saved
    if(!image.compress(Bitmap.CompressFormat.JPEG, 100, fos)) {
        Log.e(TAG, "The image could not be saved: " + imageName + " - " + imageUrl);
        image = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_cached_image);
    }
    fos.flush();
    fos.close();
    
    
    return image;
    

preload a Vector<SoftReference<Bitmap>> object with all of the bitmaps using the method above in an AsyncTask class, and also another List holding a Map of imageUrls and imageNames(for later access when you need to reload an image), then set your GridView adapter.

i recommend using an array of SoftReferences to reduce the amount of memory used. if you have a huge array of bitmaps you're likely to run into memory problems.

so in your getView method, you may have something like(where icons is a Vector holding type SoftReference<Bitmap>:

myImageView.setImageBitmap(icons.get(position).get());

you would need to do a check:

if(icons.get(position).get() == null) {
    myImageView.setImageBitmap(defaultBitmap);
    new ReloadImageTask(context).execute(position);
}

in the ReloadImageTask AsyncTask class, simply call the global method created from above with the correct params, then notifyDataSetChanged in onPostExecute

some additional work may need to be done to ensure you don't start this AsyncTask when it is already running for a particular item

like image 69
james Avatar answered Nov 19 '22 06:11

james