bitmap.copy()抛出内存不足错误

use*_*676 9 android universal-image-loader

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

    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
Run Code Online (Sandbox Code Playgroud)

我需要第二个Bitmap不可变,所以我可以借鉴它.

Igo*_*nov 14

首先尝试找一点时间阅读有关位图的正式文档:高效显示位图

它会让你了解为什么以及何时java.lang.OutofMemoryError发生.以及如何避免它.

您的问题如何:请参阅此文章:Android:将不可变位图转换为Mutable

但是从API Level 11开始,只能options.inMutable将文件加载到可变位图中.

因此,如果我们正在构建API级别低于11的应用程序,那么我们必须找到其他一些替代方案.

另一种方法是通过复制源来创建另一个位图

bitmap. mBitmap = mBitmap.copy(ARGB_8888 ,true);

但是OutOfMemoryException如果源文件很大,则会抛出.实际上,如果我们想要编辑原始文件,那么我们将面临这个问题.我们应该能够将至少图像加载到内存中,但大多数我们不能将另一个副本分配到内存中.

因此,我们必须将解码后的字节保存到某些位置并清除现有位图,然后创建一个新的可变位图并再次将保存的字节加载回位图.即使复制字节,我们也无法ByteBuffer在内存中创建另一个字节.在这种情况下需要使用 MappedByteBuffer它将在磁盘文件中分配字节.

以下代码将清楚地解释:

//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();
Run Code Online (Sandbox Code Playgroud)

这里是示例代码.