java - Android 位图重用

标签 java android bitmap garbage-collection reusability

我是 Android 新手! 我在使用 Android 的 SDK 时遇到了一些大问题,因为我正在开发一个使用巨大位图(> 1200 * 1000)的应用程序,问题是在应用程序期间我需要相同大小的多个图层/位图(其中 3-5 个) 。问题是内存堆在这些分配之一上消耗得非常快,并且会触发 OutOfMemory 异常。

好的一点是我不需要同时使用所有位图。

我尝试了 recycle() 方法调用,尽管我知道它已经过时了,因为位图的内存现在驻留在堆上,而不是 native 内存上。 我还尝试删除特定位图中的所有引用,甚至手动调用 System.gc() 但没有用,位图无法删除。 好吧,也许会有我不知道的内存泄漏,尽管我对此表示怀疑。

我尝试了各种解决方案,但都不起作用。

对我来说最好的选择是重用位图,但 BitmapFactory 的解码方法只知道分配一个消耗内存的新位图。

我的问题是,你知道一种可以在 Android 上使用的重用位图像素的方法(覆盖位图的像素而不分配另一个位图/像素数组)吗???问题是我不能驻留在 GarbageCollector 解决方案上,因为我的应用程序中有特定的时刻,我必须确定这些位图已从内存中删除/其他位图不会被分配。

另一个解决方案是:您知道一种直接在SD卡上绘制一些位图而不通过堆内存的方法吗?有时,当我尝试分配一个大位图(原始大小的两倍)来连接其他两个已处理的位图时,它会崩溃......这就是我问的原因。是否有可能直接从数据流实例化 Canvas 或其他绘图对象?

其他解决方案是使用虚拟交换内存之类的东西,它可以模拟堆内存,但在 SDCARD 或其他东西上进行缓存。但也找不到这样做的方法。

最佳答案

编写一个单独的类来执行自定义位图操作:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


class BitmapLoader
{
public static int getScale(int originalWidth,int originalHeight,
   final int requiredWidth,final int requiredHeight)
{
    //a scale of 1 means the original dimensions 
    //of the image are maintained
    int scale=1;

    //calculate scale only if the height or width of 
    //the image exceeds the required value. 
    if((originalWidth>requiredWidth) || (originalHeight>requiredHeight)) 
    {
        //calculate scale with respect to
        //the smaller dimension
        if(originalWidth<originalHeight)
            scale=Math.round((float)originalWidth/requiredWidth);
        else
          scale=Math.round((float)originalHeight/requiredHeight);

    }

    return scale;
}

public static BitmapFactory.Options getOptions(String filePath,
        int requiredWidth,int requiredHeight)
{

    BitmapFactory.Options options=new BitmapFactory.Options();
    //setting inJustDecodeBounds to true
    //ensures that we are able to measure
    //the dimensions of the image,without
    //actually allocating it memory
    options.inJustDecodeBounds=true;

    //decode the file for measurement
    BitmapFactory.decodeFile(filePath,options);

    //obtain the inSampleSize for loading a 
    //scaled down version of the image.
    //options.outWidth and options.outHeight 
    //are the measured dimensions of the 
    //original image
    options.inSampleSize=getScale(options.outWidth,
            options.outHeight, requiredWidth, requiredHeight);

    //set inJustDecodeBounds to false again
    //so that we can now actually allocate the
    //bitmap some memory
    options.inJustDecodeBounds=false;

    return options;

}



public static Bitmap loadBitmap(String filePath,
        int requiredWidth,int requiredHeight){


    BitmapFactory.Options options= getOptions(filePath,
            requiredWidth, requiredHeight);

    return BitmapFactory.decodeFile(filePath,options);
}
}

然后从您的 Activity 中调用此类的 Bitmap reqBitmap = loadBitmap(String filePath,int requiredWidth,int requiredHeight) 方法,提供从sd 卡,并将 requiredWidth 和 requiredHeight 设置为您希望将位图缩放到的尺寸。现在使用reqBitmap

这样,大位图在加载到堆内存之前将被缩小。我遇到了同样的问题,这为我解决了。 :)

关于java - Android 位图重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13011424/

相关文章:

android - 如何正确使用com.octo.android.robospice来缓存位图

c++ - 创建具有给定尺寸并填充给定颜色的新位图

java - 测试完成后如何触发发送 TestNG 可通过电子邮件发送的报告

java - 使我的 Java 程序与外部类文件交互

java - 为什么复选框中的框不可见?

android - 我的应用程序使用大量 Ram 并意外关闭

java - 同步调整 jPanel 组件的大小

java - onDestroy() 方法上出现 NullPointerException

java - 在 list 中关闭接收器

java.lang.IllegalArgumentException : AppCompat does not support the current theme features