我有一个应用程序需要非常快速地访问大量图像,所以我需要以某种方式将这些图像加载到内存中。这样做的位图使用超过100MB的RAM,这是完全不可能的,所以我选择将jpg文件读入内存,将它们存储在byteArray中。然后我解码它们并在需要时将它们写入画布。这非常有效,可以减少磁盘访问速度,同时还可以考虑内存限制。
然而,内存使用对我来说似乎“关闭”。我正在存储450个jpgs,每个文件大小约为33kb。这总计约15MB的数据。但是,Eclipse DDMS和Android(在物理设备上)报告的应用程序持续运行在35MB到40MB之间的RAM。我已经尝试修改加载了多少jpgs,并且应用程序使用的RAM往往会减少大约每个jpg 60-70kb,这表明每个图像都存储在RAM中两次。内存使用量不会波动,这意味着不会涉及实际的“泄漏”。
以下是相关的加载代码:
private byte[][] bitmapArray = new byte[totalFrames][];
for (int x=0; x<totalFrames; x++) {
File file = null;
if (cWidth <= cHeight){
file = new File(directory + "/f"+x+".jpg");
} else {
file = new File(directory + "/f"+x+"-land.jpg");
}
bitmapArray[x] = getBytesFromFile(file);
imagesLoaded = x + 1;
}
public byte[] getBytesFromFile(File file) {
byte[] bytes = null;
try {
InputStream is = new FileInputStream(file);
long length = file.length();
bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file " + file.getName());
}
is.close();
} catch (IOException e) {
//TODO Write your catch method here
}
return bytes;
}
最终,他们会像这样写入屏幕:
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
int canvasWidth = c.getWidth();
int canvasHeight = c.getHeight();
Rect destinationRect = new Rect();
destinationRect.set(0, 0, canvasWidth, canvasHeight);
c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[bgcycle], 0, bitmapArray[bgcycle].length), null, destinationRect, null);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
我是否认为这里存在某种重复?或者,像这样在byteArray中存储jpgs会有多少开销?
答案 0 :(得分:1)
在RAM中存储字节与在硬盘驱动器上存储数据有很大不同......它有很多开销。对象的引用以及字节数组结构都占用了额外的内存。所有额外的内存并不是真正的单一来源,但记住比将文件加载到RAM通常占用2到3倍的空间(根据经验,我恐怕不能引用任何内容)这里的文件)。
考虑一下:
File F = //Some file here (Less than 2 GB please)
FileInputStream fIn = new FileInputStream(F);
ByteArrayOutputStream bOut = new ByteArrayOutputStream(((int)F.length()) + 1);
int r;
byte[] buf = new byte[32 * 1000];
while((r = fIn.read(buf) != -1){
bOut.write(buf, 0, r);
}
//Do a memory measurement at this point. You'll see your using nearly 3x the memory in RAM compared to the file.
//If your actually gonna try this, remember to surround with try-catch and close the streams as appropriate.
还要记住,未使用的内存不会立即被清除。方法getBytesFromFile()可能返回一个字节数组的副本,这会导致内存重复,这可能不会立即被垃圾回收。如果您想要安全,请检查方法getBytesFromFile(file)是否泄漏了应该清理的任何引用。它不会出现内存泄漏,因为您只能将其称为有限次数。
答案 1 :(得分:0)
这可能是因为你的字节数组是2维的,你只需要一个维度来使用字节数组加载图像,而第二个维度可能会使所需的Ram加倍,因为每个字节都是空的但仍然存在你不使用的字节