ViewFlipper:OutOfMemoryError:位图大小超过VM预算

时间:2011-11-22 13:52:21

标签: android viewflipper out-of-memory

我在我的Android应用程序中使用ViewFlipper。在调用startflipping()之后,如果我让app运行几分钟,我很快就会收到错误:

11-22 15:36:34.354: ERROR/dalvikvm-heap(428): 307200-byte external allocation too large for this process.
11-22 15:36:34.372: ERROR/(428): VM won't let us allocate 307200 bytes
11-22 15:36:34.375: ERROR/AndroidRuntime(428): Uncaught handler: thread main exiting due to uncaught exception
11-22 15:36:34.384: ERROR/AndroidRuntime(428): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459)
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:271)
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:296)
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at com.PlayerOrange.ViewPlaylist.populate(ViewPlaylist.java:115)
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at com.PlayerOrange.ViewPlaylist.access$0(ViewPlaylist.java:100)
11-22 15:36:34.384: ERROR/AndroidRuntime(428):     at com.PlayerOrange.ViewPlaylist$ProgressTask$1$1.run(ViewPlaylist.java:383)

每隔30秒我会得到一些关于内存的信息:

ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(ACTIVITY_SERVICE);
                android.app.ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
                activityManager.getMemoryInfo(memoryInfo);

                Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
                Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
                Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );

奇怪的是,在我获得Force Close之前(因为outofmemoryError)我在DDMS中有这个:

11-22 15:36:10.255: INFO/(428):  memoryInfo.availMem 50470912
11-22 15:36:10.255: INFO/(428):  memoryInfo.lowMemory false
11-22 15:36:10.264: INFO/(428):  memoryInfo.threshold 16777216

我不知道如何解决这个错误。

以下是填充ViewFlipper的代码:

private void populate() {
        for (int i = 0; i < jArray.length(); i++) {
            System.out.println("lungime" + jArray.length());
            LinearLayout l = new LinearLayout(this);
            l.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
                    LayoutParams.FILL_PARENT));
            l.setBackgroundColor(0x000000);
            l.setOrientation(LinearLayout.VERTICAL);
            vf.addView(l);

            File f = new File(Environment.getExternalStorageDirectory()
                    + "/Downloads/");

            File[] files = f.listFiles();

            Bitmap bitmap = BitmapFactory.decodeFile(files[i].getPath());
            img = new ImageView(this);
            img.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
                    LayoutParams.FILL_PARENT));

            img.setImageBitmap(bitmap);

            System.out.println("target " + target[i]);
            img.setOnTouchListener(this);
            img.setId(i);

            l.addView(img);
            img = null;

        }

vf = (ViewFlipper) findViewById(R.id.details);
            vf.setFlipInterval(Integer.valueOf(timer) * 1000);
            vf.startFlipping();
            populate();

我从网上获取图片并保存到Sdcard。之后,我从SDcard文件夹中获取它们并将它们添加到viewFlipper。

欢迎任何想法。提前致谢。

3 个答案:

答案 0 :(得分:1)

  1. 使用一些缓存机制来减少内存使用量。
  2. 使用BitmapFactory.Options http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html
  3. 缩小图像

    这里的缓存意味着使用某种数据结构,可以保持对图像的有效引用。这只是意味着您可以根据需要通过缓存访问图像,缓存将尝试仅按需要保留对所需图像的引用。这通常是使用SoftReference完成的:http://download.oracle.com/javase/6/docs/api/java/lang/ref/SoftReference.html  甚至是WeakReferencehttp://download.oracle.com/javase/6/docs/api/java/lang/ref/WeakReference.html

    以下是一个示例:https://github.com/thest1/LazyList

答案 1 :(得分:1)

你只是使用太多&amp;太大的位图图像。

如果你的内存中有太多的图像会导致OutOfMemoryException,因为Bitmaps实际上只是巨大的二维数组。

正如在其他答案中所说,你可以做两件事:减少图像的大小或一次减少内存中的图像数量。

您可以使用缓存或弱引用,您可以动态缩小位图。这些是比较先进的技术。你最好打赌,如果可能的话,只需使用更小的位图作为你的来源。

如果你不能,这是一个简单的解决方案:

        img.setImageBitmap(bitmap);
        bitmap.recycle();
        System.out.println("target " + target[i]);

这应该更快地清理Bitmap对象。有关详细信息,请参阅以下内容:recycle

答案 2 :(得分:0)

以下相关内容已被专家质疑和回答。

OutOfMemoryError:位图大小超过VM预算

请查看以下链接:

Strange out of memory issue while loading an image to a Bitmap object