首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bitmap.copy()抛出内存错误

bitmap.copy()抛出内存错误
EN

Stack Overflow用户
提问于 2014-05-20 15:01:05
回答 6查看 6.4K关注 0票数 9

我使用universal-image-loader库来加载图像,但在某些情况下,当我在加载的位图文件上调用copy()时,就会得到OutOfMemoryError。这是我的代码:

代码语言:javascript
复制
    ImageLoader.getInstance().loadImage(path, new ImageLoadingListener() {

        @Override
        public void onLoadingStarted(String arg0, View arg1) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
            bm = arg2;
        }

        @Override
        public void onLoadingCancelled(String arg0, View arg1) {
            // TODO Auto-generated method stub

        }
    });
 Bitmap bm2= bm.copy(Bitmap.Config.ARGB_8888, true); //where the crash happens

我需要第二个Bitmap不能变,这样我就可以使用它了。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-06-04 10:18:21

首先,尝试找出一点时间来阅读关于位图的好的官方文档:高效显示位图

它将使您了解java.lang.OutofMemoryError发生的原因和时间。以及如何避免。

那么你的问题呢:参见本文:Android:将不可变位图转换为可变位图

但是从API 11中,只有options.inMutable可以将文件加载到可变位图中。 因此,如果我们构建API级别小于11的应用程序,那么我们必须找到其他的替代方案。 一种选择是通过复制源创建另一个位图。 bitmap. mBitmap = mBitmap.copy(ARGB_8888 ,true); 但是,如果源文件很大,则将抛出OutOfMemoryException。实际上,如果我们想编辑一个原始文件,那么我们将面临这个问题。我们应该能够-至少将图像加载到内存,但大多数我们不能分配另一个副本到内存。 因此,我们必须将解码后的字节保存到某个位置并清除现有位图,然后创建一个新的可变位图并将保存的字节重新加载到位图中。即使要复制字节,我们也不能在内存中创建另一个ByteBuffer。在这种情况下,需要使用MappedByteBuffer来在磁盘文件中分配字节。 下面的代码将解释清楚:

代码语言:javascript
复制
//this is the file going to use temporally to save the bytes. 

File file = new File("/mnt/sdcard/sample/temp.txt");
file.getParentFile().mkdirs();

//Open an RandomAccessFile
/*Make sure you have added uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
into AndroidManifest.xml file*/
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); 

// get the width and height of the source bitmap.
int width = bitmap.getWidth();
int height = bitmap.getHeight();

//Copy the byte to the file
//Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, width*height*4);
bitmap.copyPixelsToBuffer(map);
//recycle the source bitmap, this will be no longer used.
bitmap.recycle();
//Create a new bitmap to load the bitmap again.
bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
map.position(0);
//load it back from temporary 
bitmap.copyPixelsFromBuffer(map);
//close the temporary file and channel , then delete that also
channel.close();
randomAccessFile.close();

这里是样例代码。

票数 15
EN

Stack Overflow用户

发布于 2014-05-20 15:08:43

除了确保正在复制或显示的位图不太大外,您无法对位图的外部内存错误做更多的处理。幸运的是,通用imageloader有一个通过更改配置来压缩位图的功能。所以让Bitmap.Config.RGG_565试一试。它应该是位图内存足迹的一半。您还可以请求较大的堆大小。您可以做的另一件事是复制位图的缩放版本。

票数 3
EN

Stack Overflow用户

发布于 2014-06-03 20:30:54

感谢它发生在您的设备上,而不仅仅是在用户的设备上。

1)这是你必须处理的事情,并对此作出适当的反应。显示错误信息,或加载位图的较低分辨率。您的应用程序将运行在多种设备上,每个设备都有不同的内存。

2)每次操作后使用重要函数Bitmap.recycle,使原来的位图冗余。这将立即释放内存用于下一个工作,而无需等待GC运行,并且可能会出现内存错误。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23763405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档