Android:关于位图,内存使用和扩展的问题

ab1*_*b11 14 android memory-management bitmap

为了便于阅读,我首先发布了我的解决方案所引用的代码示例,然后我在数字列表中列出了我的解决方案的解释.

我一直在努力解决这个问题.我做了很多阅读,在这里问了问题,并进行了实验; 但还没有找到一个像样的解决方案.我需要从输入流中读取各种大小的图像,并以我的内存约束允许的高质量显示它们.以下是我考虑过的选项,这些选项对我来说都不是很好.任何帮助或输入将不胜感激.

 public class NativeTest extends Activity
 {
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
       super.onCreate(savedInstanceState);
       double nativeUsage = Debug.getNativeHeapAllocatedSize(); 
       Log.i("memory", nativeUsage+"");
    } 
 }


 double getAvailableMemory()
 {
    //current heap size 
     double heapSize =  Runtime.getRuntime().totalMemory();
    //amount available in heap 
    double heapRemaining = Runtime.getRuntime().freeMemory();   
    double nativeUsage  =  Debug.getNativeHeapAllocatedSize();
     double memoryAvailable = Runtime.getRuntime().maxMemory() - (heapSize - heapRemaining) - nativeUsage;
    return memoryAvailable;
 }

Bitmap createImageTrialAndError(InputStream stream)
{
    Bitmap image = null;
    int dowsample = 1;
    while(image == null)
    {
       try
       {    
        Options opts = new Options();
        opts.inSampleSize =  downsample;
        image = BitmapFactory.decodeStream(imgStream, null, opts);
       }
       catch (OutOfMemoryError ome)
       {
           downsample = downsample * 2;
           Log.i("out of mem", "try using: " + downsample); 
       }
    }

    return image;
}
Run Code Online (Sandbox Code Playgroud)
  1. 理想的解决方案是Bitmap有Bitmap.drawBitmap(inputstream ...)方法.这将允许我从输入流中绘制而无需为Bitmap分配内存.唉,这不是一个选择.
  2. 根据可用内存缩放位图.这涉及检索Bitmap的宽度和高度,计算Bitmap所需的字节数width * height * 4,计算可用内存,然后BitmapFactory.Options.inSampleSize使Bitmap使用的内存少于可用内存.但是,此选项失败,因为我无法找到一种可靠的远程计算可用内存的方法.下面的getAvailableMemory()方法似乎应该可以工作:它将可用内存计算为最大内存 - 在java堆中使用的内存 - 在本机堆中使用的内存.
    不幸的是,这个公式给出了非常不可靠的结果.主要是因为Debug.getNativeHeapAllocatedSize()似乎没有准确表示位图内存使用情况.其不准确性的一个明显例子是下面的NativeTest活动.在我的三星Galaxy平板电脑上,输出的日志声明为:3759416.0.3.75 mb的空活动原生分配,显然不是确定位图缩放的可靠方法.
  3. 以缩放因子1开始,并尝试初始化位图; 如果由于内存导致初始化失败,则将缩放因子加倍并重试; 并重复此过程直到成功.这说明了createBitmapTrialAndError().这实际上是惊人的有效而且不是非常慢.但是,这是非常不受欢迎的,因为我在我的应用程序的其他地方使用SoftReferences,并且内存不足会强制收集这些SoftReferences,这会对性能产生重大影响.最初需要知道适当的缩放因子,这将避免不必要地收集这些SoftReferences.
  4. 我的最终解决方案似乎有点可疑.基本上它结合了2和3,但不使用Debug.getNativeAllocatedSize().相反,我跟踪自己的Bitmap内存分配,通过跟踪我分配位图和计算其内存使用量的任何位置,然后减去我回收的任何位图的内存使用量.我使用此值代替getAvailableMemory()中的nativeUsage,以便计算位图的正确缩放因子.如果在使用此方法时发生Out Of Memory异常,我使用解决方案3作为计算可接受比例的后备方式.显而易见的问题是试图跟踪我自己的本机内存使用量的大量粗略,但对我来说,它似乎是最好的解决方案.

dev*_*snd 0

Android 堆的问题是,您实际上不知道可以使用多少堆,因为如果您超出内存限制,任何后台服务都可能随时毁掉您的一切。

为什么不只保留一个与您始终在其上绘制的画布大小相同的位图,以及一堆下采样的位图?然后,您可以将本机解决方案中的所有图像渲染到画布上,并始终为发生的任何更改绘制下采样位图。更改结束后,或者清楚哪张图像最重要,以本机分辨率将该图像重新绘制到画布上(通过再次访问磁盘)。