How do I allow multiple bit-map galleries in a tabhost without exceeding the VM limit in android?
In my main activity (with launchmode
set as singleTask
), I have a TabHost
with three tabs, which all contain a custom Gallery
that displays Views
containing a bitmap
image which is stored locally (once we have server support, these will be downloaded instead).
The problem I am running into is the java.lang.OutOfMemoryError: bitmap size exceeds VM budget
error (on my emulator. It works terrific on my Galaxy Tab). I understand that this means I am using too many bitmaps
of large sizes without recycling them, however I am having difficulty figuring out the best place to recycle them, since each tab remains running in the background when another tab is selected.
Do I need to change my Gallery adapter to only have a few bitmaps loaded at once (such as the selected, left, and right views), or is 开发者_Go百科there a simpler solution (for example, a good place to call recycle()
)?
Edit: I tried using this code, and called it when a new gallery item is selected. It worked at first, but then the app still crashed. Am I not calling recycle() correctly?
/* *
* Set the current, left, and right view's images. Set all others to NULL and recycle them.
*/
public void refreshImages() {
for (int i = 0; i < adapter.getCount(); i++) {
View v = adapter.getView(i, null, null);
ImageView img = (ImageView) v.findViewById(R.id.add_image);
Thing mything = adapter.getThing(i);//returns a Thing object at this position in the gallery.
if (i == currentGalleryPosition //This is set when the gallery item is selected.
|| i == (currentGalleryPosition - 1)
|| i == (currentGalleryPosition + 1)) {
img.setImageBitmap(thing.getImage(this)); //This retrieves the bitmap from my drawable resources.
img.setScaleType(ImageView.ScaleType.FIT_XY);
}
else {
Bitmap bmp = thing.getImage();
img.setImageBitmap(null);
bmp.recycle();
}
}
}
maybe System.gc();
. Use it to call the garbage collector .
One tip : I would use it whenever someone click on a tab , or when you pass for example 10 images.
This is not the best solution, but it does what I need it to do:
When decoding a bitmap, set the inPurgeable and inInputShareable options to true. This makes it so that if the VM needs more space, it can simply remove images (purge), but if you are sharing multiple images amongst multiple tabs, the inInputShareable option allows the decoder to simply share the same location in memory, without creating a new instance of the same bitmap.
BitmapFactory.Options o = new BitmapFactory.Options();
o.inDither = true;
o.inPurgeable = true;
o.inInputShareable = true;
return BitmapFactory.decodeResource(getResources(), R.drawable.img, o);
精彩评论