Showing Large Images On View Pager From Sdcard In Android
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"