Skip to content Skip to sidebar Skip to footer

Showing Large Images On View Pager From Sdcard In Android

I have a problem that I have 80 to 150 images of very High Resolution and I have to show them in a view pager. I had written the simple mechanism of decoding but get OutofMemory Er

Solution 1:

inJustDecodeBounds & inSampleSize

You are decoding high resolution images at each PagerAdapter call, and if you are willing to reduce the decoded bitmap memory by powers of 2 (x/2, x/4 ... x : original bitmap size), then go for this method


Bitmap.recycle()

A very handy method, when used at the right place, can work wonders. I am assuming that you are setting a BitmapDrawable or calling setImageBitmap to an ImageView. Add the following snippet in destroyItem() callback of PagerAdapter.

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    View view = (View) object;
    ImageView imageView = (ImageView) view.findViewById(R.id.image_view);
    Drawable drawable = imageView.getDrawable();
    if(drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if(bitmapDrawable != null) {
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if(bitmap != null && !bitmap.isRecycled()) bitmap.recycle();    
        }
    }
    ((ViewPager) container).removeView(view);
}

The idea is that when any child view is removed from Pager, its bitmap should get recycled, that way you would not depend on GC calls to clear memory for you.


largeHeap = true

Add this property in Manifest.xml <application> tag. Wherever largeHeap is supported, it will increase heap memory to some large value, even goes till 8 times.


Also, in general don't hold any silly references to any bitmap, just decode them and assign it to View, rest will be taken care of.

Hope that helps. :)


Solution 2:

I'll suggest you to look at official android developers sample code called BitmapFun and use it for your purpose. Actually you missed o2.inPurgable=true; Also there is no need to use o and o2, o is good enough.

 //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //The new size we want to scale to
            final int REQUIRED_SIZE=550;

            //Find the correct scale value. It should be the power of 2.
            int scale=1;
            while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
                scale*=2;

            //Decode with inSampleSize
            //BitmapFactory.Options o2 = new BitmapFactory.Options();
            o.inSampleSize=scale;
            o.inJustDecodeBounds = false;
            o.inPurgealbe = true;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o);
        } catch (FileNotFoundException e) {}
        return null;
    }

Solution 3:

Remove the line bitmap = BitmapFactory.decodeFile(path + "/" + imageName + ".png"); from your Drawable getImageFromSdCard(String imageName) method to begin with. Also remove the bitmap variable in that method since it´s unused, now you have removed unnecessary allocations, the problem you experience could be that the GC simply does not cope with the amount of garbage / allocations that was made since you did twice as many that was needed. The method should look something like:

public Drawable getImageFromSdCard(String imageName) {
    Drawable d = null;
    String path = Environment.getExternalStorageDirectory()+"/MAGZ/"+magName+"/"+magName+issueName;
    d = new BitmapDrawable(decodeFile(new File(path+"/"+imageName+".png")));
    return d;
}

Also reuse your o variable in decodeFile method just remember to flip the boolean inJustDecodeBounds after the first call.

Also do not catch runtime exceptions, bad practice, they're there because of just runtime errors. You´re hiding the real problem by catching them.

BitmapDrawable(Bitmap bitmap) constructor has been deprecated since api version 4, checkout BitmapDrawable for what constructor you should be using.


Post a Comment for "Showing Large Images On View Pager From Sdcard In Android"