我正在处理我正在处理的Android应用程序上的位图问题。假设发生的是应用程序从网站下载图像,将它们保存到设备,将它们作为位图加载到内存中,并将其显示给用户。首次启动应用程序时,这一切都正常。但是,我为删除了图像的用户添加了一个刷新选项,上面概述的过程从头开始。
我的问题:通过使用刷新选项,旧图像仍然在内存中,我很快就会得到OutOfMemoryErrors。因此,如果图像正在刷新,我让它通过arraylist并回收旧图像。但是,当应用程序将新图像加载到arraylist中时,它会因“尝试使用回收的位图”错误而崩溃。
据我了解,回收位图会破坏位图并为其他对象释放内存。如果我想再次使用位图,则必须重新初始化。我相信当新文件加载到arraylist时我正在这样做,但是仍然有问题。非常感谢任何帮助,因为这非常令人沮丧。问题代码如下。谢谢!
public void fillUI(final int refresh) {
// Recycle the images to avoid memory leaks
if(refresh==1) {
for(int x=0; x<images.size(); x++)
images.get(x).recycle();
images.clear();
selImage=-1; // Reset the selected image variable
}
final ProgressDialog progressDialog = ProgressDialog.show(this, null, this.getString(R.string.loadingImages));
// Create the array with the image bitmaps in it
new Thread(new Runnable() {
public void run() {
Looper.prepare();
File[] fileList = new File("/data/data/[package name]/files/").listFiles();
if(fileList!=null) {
for(int x=0; x<fileList.length; x++) {
try {
images.add(BitmapFactory.decodeFile("/data/data/[package name]/files/" + fileList[x].getName()));
} catch (OutOfMemoryError ome) {
Log.i(LOG_FILE, "out of memory again :(");
}
}
Collections.reverse(images);
}
fillUiHandler.sendEmptyMessage(0);
}
}).start();
fillUiHandler = new Handler() {
public void handleMessage(Message msg) {
progressDialog.dismiss();
}
};
}
答案 0 :(得分:19)
您实际上并不需要在此处调用回收方法。刷新按钮应该只清除数组,垃圾回收器将在以后释放内存。如果你得到OutOfMemory,这意味着其他一些对象仍然引用你的旧图像,垃圾收集器无法删除它们。
我可能会认为某些ImageView会显示您的位图,并且它们会保留对该位图的引用。您仍然无法删除旧位图。因此,一个可能的解决方案是清除ImageVIews。之后,您可以清除阵列并用新图像填充它。
Recycle释放了内存,但是一些ImageView仍然显示位图,并且在回收后无法执行此操作,这就是“尝试使用回收位图”的原因。
这些只是一个假设,因为我看不到你的完整代码。
答案 1 :(得分:4)
如果内存非常大,您最好自己回收位图。 GC无法控制。