我正在处理一个打开图像、播放图像并保存的项目。该图像可以是非常大的图像,例如相机照片,因此我正在做几件事以确保不会出现 OutOfMemory 异常(基本上是此处显示的 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html ):
- 在不实际打开图像的情况下执行图像宽度和高度的所有测量,使用:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image_path, options);
打开已调整大小 (inSampleSize) 并使用
Bitmap.Config.RGB_565
的图像(每像素 2B)除了Bitmap.Config.ARGB_8888
(每像素 4B)。使用临时文件到内存中没有很多位图(实际上我只有一种情况,应用蒙版时最多 2 个)。
使用后回收每个位图
在
ImageView
中显示结果时, 打开它已经缩放到屏幕尺寸。
但是,在某些情况下,不可能一次只加载一个位图来完成某项工作(旋转图像、微调调整大小、应用蒙版……),并且大多数情况下处于中等范围或较旧设备,我收到一个OutOfMemory 异常。
我已经开始添加所有在后台作业中工作的图像,如下所示(好吧,我是新手):
ProgressDialog dialog = ProgressDialog.show(this, null, "Please wait", true, false);
new Thread(new BackgroundJob(this, new Runnable() {
public void run() {
ImageHelper.ImageManipulation(image_path);
}
}, dialog, new Handler())).start();
我希望通过这个新线程获得完全可用的内存空间来执行图像处理任务,但我发现该应用程序因相同原因在相同点崩溃。线程被创建为子进程(好)但共享最大堆和当前使用的内存...
有没有办法打开一个线程来执行具有更多内存的图像处理(例如,释放 Activity 本身使用的内存,因为它是另一个线程)?
非常感谢。
最佳答案
在 Android 设备上进行内存管理时,有很多陷阱 - 特别是当您将不同的设备混在一起时。去年我浪费了时间在我制作的不同 Android 应用程序中玩内存管理,直到我发现 Android-BitmapCache project。我取得了一些重大进展。
我建议所有对Android内存管理感兴趣的人download and inspect Android-BitmapCache project ,因为它包含一些很棒的代码 - 所以将其作为第一步。
我建议您的第二步是观看 Google I/O: Memory Management for Android Apps主要是为了让您可以开始准确测试您的应用程序使用了多少内存,并跟踪确切的内存使用量从哪里开始增加。说到这一点——我不明白你为什么认为你会获得“新线程的完全可用内存空间”——你从你的 Android 应用程序中产生的所有线程都将处于同一进程中,所以哪个确切的并不重要当涉及到内存使用时,线程正在运行一些任务。
最后,您可以使用 android:largeHeap="true" 临时解决问题,但我认为您绝对应该以更强大的解决方案为目标。请记住,在某些设备上,您的应用程序可能根本无法运行(24MB 堆并且您想要加载 3000x3000 的图像),但是应用所有最佳实践后,您可以在 project I've linked 中找到我相信你会过得更好。
关于android - 在单独的线程中处理位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15321290/