Android, concern over VM heap size
After some testing with a completed product, I have just found that the hardware devices I have all have large VM Heaps.
The lowest being 32MB.
My application is a memory intensive application that loads a bunch of high quality, alpha images and draws them to the canvas as an an开发者_运维问答imation. There can be up to two sets of these loaded (one for the current animation and one for the next)
I am now concerned after having decreased the VM Heap Size on one of my devices to 16MB that it won't in fact run on devices with a heap size that small.
Since I can not do much about the size of the images, and there is little I can do to reduce the number of images, I ask how would I go about chieving the same result with less stringent memory restrictions?
Thanks
When you say high quality, do you mean high resolution? My suggestion is that you only store in memory what you need to display on screen, and store the rest on the filesystem. You could then process it in chunks in the background. Not sure if that'll work for you, I don't really understand what your app does.
You can use this method to decode the images. It may make them much lighter. Remember that images become bitmaps when they are shown increasing their memory consuption.
public static Bitmap decode(byte[] imageByteArray, int width, int height) {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length,
o);
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < width || height_tmp / 2 < height)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
o2.inTempStorage = new byte[Math.max(16 * 1024, width * height * 4)];
return BitmapFactory.decodeByteArray(imageByteArray, 0,
imageByteArray.length, o2);
// return BitmapFactory.decodeByteArray(imageByteArray, 0,
// imageByteArray.length);
}
where
width - MAX width in pixels that the imageView might have. height - MAX height in pixels that the imageView might have.
That way, the bitmap will become lighter and the app might consume less memory.
(NOTE: I copied this method and modified it a little bit, I don't remember the original question so i cant put the url)
I use to strore the images in byte arrays and I only decode them just before showing them.
Now, like James L says, its best to keep the images in the fileSystem and only bring to memory when needed, but if you an't do that (my case). you can download images with:
public static byte[] getBytes(InputStream is) throws IOException {
int len;
int size = 1024;
byte[] buf;
if (is instanceof ByteArrayInputStream) {
size = is.available();
buf = new byte[size];
len = is.read(buf, 0, size);
} else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
buf = new byte[size];
while ((len = is.read(buf, 0, size)) != -1)
bos.write(buf, 0, len);
buf = bos.toByteArray();
}
return buf;
}
public static byte[] downloadFileByteArray(String fileUrl)
throws IOException, MalformedURLException {
URL myFileUrl = null;
myFileUrl = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
return getBytes(is);
}
If you allready have the images in memory you will be able to turn them into byte arrays by loking at the methods I present.
Other than that (and calling System.gc()) there is not much you can do (that I know of). Maybe dleting the BMPs in the onPause() and onDestroy() and recostructing them in the onResume() if necesary.
精彩评论