【问题标题】:Grow heap (frag case) to 8.837MB for 6220816-byte allocation error为 6220816 字节分配错误将堆(碎片情况)增加到 8.837MB
【发布时间】:2015-01-09 13:56:45
【问题描述】:

我正在尝试使用 15 到 20 张图像在固定时间一张一张地显示在动态壁纸背景上,但我面临堆增长问题(将堆(碎片情况)增长到 8.987MB 以分配 6220816 字节)我有搜索一切,但无法通过这个 任何帮助请求。

这是我的代码

公共类 LiveWallpaperService 扩展 WallpaperService {

private float x;
private int y;
private int angle;
private int speed;

@Override
public void onCreate() {
    super.onCreate();
}

@Override
public void onDestroy() {
    super.onDestroy();
}

@Override
public Engine onCreateEngine() {
    stopSelf();
    return new MyWallpaperEngine();
}

class MyWallpaperEngine extends Engine {

    private final Handler handle = new Handler();
    private final Runnable drawRunner = new Runnable() {

        @Override
        public void run() {
            draw();
        }
    };

    private Boolean visble = true;
    public Bitmap mBackgroundImage;
    public String name;
    int[] mImagesArray;
    private int mImagesArrayIndex = 0;

    MyWallpaperEngine() {

        mImagesArray = new int[] { R.drawable.love_1_mini,
                R.drawable.love_2_mini, R.drawable.love_3_mini,
                R.drawable.love_4_mini, R.drawable.love_5_mini,

                R.drawable.love_6_mini, R.drawable.love_7_mini,
                R.drawable.love_8_mini, R.drawable.love_9_mini,
                R.drawable.love_10_mini,

                R.drawable.love_11_mini, R.drawable.love_12_mini,
                R.drawable.love_13_mini, R.drawable.love_14_mini,
                R.drawable.love_15_mini, R.drawable.love_16_mini,
                R.drawable.love_17_mini, R.drawable.love_18_mini,
                R.drawable.love_19_mini, R.drawable.love_20_mini };

        if (mImagesArrayIndex == 0) {
            x = -330; // initialize x position
            y = 0; // initialize y position
        } else {
            x = -330; // initialize x position
            y = 0; // initialize y position
        }

    }

    @Override
    public Bundle onCommand(String action, int x, int y, int z,
            Bundle extras, boolean resultRequested) {
        return super.onCommand(action, x, y, z, extras, resultRequested);
    }

    @Override
    public void onCreate(SurfaceHolder surfaceHolder) {
        super.onCreate(surfaceHolder);
    }

    @Override
    public void onOffsetsChanged(float xOffset, float yOffset,
            float xOffsetStep, float yOffsetStep, int xPixelOffset,
            int yPixelOffset) {
        draw();
    }

    @Override
    public void onSurfaceCreated(SurfaceHolder holder) {
        super.onSurfaceCreated(holder);
        this.visble = false;

    }

    @Override
    public void onTouchEvent(MotionEvent event) {

    }

    @Override
    public void onVisibilityChanged(boolean visible) {
        this.visble = visible;
        if (visible) {
            handle.post(drawRunner);
        } else {
            handle.removeCallbacks(drawRunner);
        }

        super.onVisibilityChanged(visible);
    }

    private void incrementCounter() {
        mImagesArrayIndex++;
        if (mImagesArrayIndex >= mImagesArray.length) {
            mImagesArrayIndex = 0;

        }

    }

    @SuppressWarnings("deprecation")
    void draw() {

        int count = mImagesArray[mImagesArrayIndex];
        final SurfaceHolder holder = getSurfaceHolder();
        Canvas c = null;
        int scale = 2;
        Resources res = getResources();
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inPreferredConfig = Bitmap.Config.RGB_565;
        o2.inSampleSize = scale;
        o2.inPurgeable = true;
        o2.inInputShareable = true;
        Bitmap image = BitmapFactory.decodeResource(res, count, o2);

        Calendar mCalendar = Calendar.getInstance();
        int h = mCalendar.get(Calendar.HOUR);
        int m = mCalendar.get(Calendar.MINUTE);
        int s = mCalendar.get(Calendar.SECOND);

        if (s == 10) {
            mImagesArrayIndex = 0;
        }

        try {
            Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
            c = holder.lockCanvas();
            c.drawColor(Color.RED);

            if (c != null) {
                int a = 0;
                int counting = 0;
                if (counting == a) {
                    a++;
                    counting++;

                    c.drawBitmap(image, x, y, paint);

                    int widthhhh = c.getWidth();

                    x = (float) (x + 10.10);

                    if (x > widthhhh + 400) {

                        image.recycle();
                        image = null;
                        incrementCounter();

                    }

                }

                paint.setColor(Color.RED);

            }

        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } finally {

            try {
                if (c != null) {
                    holder.unlockCanvasAndPost(c);
                }
                handle.removeCallbacks(drawRunner);
                if (visble) {
                    handle.postDelayed(drawRunner, 10);
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
        }
    }

}

}

【问题讨论】:

    标签: android


    【解决方案1】:

    位图图像 = BitmapFactory.decodeResource(getResources(), mImagesArray[mImagesArrayIndex]);

    完成后请致电image.recycle()(请参阅javadoc)。

    【讨论】:

    • 请解释为什么必须使用recycle() 以及为什么它很重要。
    • 但我在这行 c.drawBitmap(image, x, y, paint); image.recycle();图像=空;
    • 当您或任何其他对象不再以任何方式使用 Bitmap 时,您调用 recycle()。您还可以设置 myBitmap = null 让对象本身被垃圾收集。
    【解决方案2】:

    在您的 draw() 方法中,您有以下代码:

        Bitmap image = BitmapFactory.decodeResource(getResources(),
                mImagesArray[mImagesArrayIndex]);
        int count = mImagesArray[mImagesArrayIndex];
        final SurfaceHolder holder = getSurfaceHolder();
        Canvas c = null;
        int scale = 4;
        Resources res = getResources();
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inPreferredConfig = Bitmap.Config.RGB_565;
        o2.inSampleSize = scale;
        o2.inPurgeable = true;
        o2.inInputShareable = true;
        image = BitmapFactory.decodeResource(res, count, o2);
    

    注意第一行调用BitmapFactory.decodeResource()并将结果分配给变量image,然后,最后一行再次调用BitmapFactory.decodeResource()并分配结果到变量image。您从未在第一个解码图像上调用recycle(),所以这会给您带来内存泄漏。

    【讨论】:

    • 好的,我删除了它,但它仍然显示错误,因为 GC_FOR_ALLOC 已释放 381K,15% 可用 3056K/3564K,暂停 8 毫秒,定期总共 8 毫秒
    • 这不是错误,它只是垃圾收集器的进度日志。这意味着您每 X 毫秒创建价值 381K 的对象。
    • 您正在解码资源并在您的 draw() 方法中每 10 毫秒创建 2 个图像!也许你需要重新考虑这个架构!为什么需要每 10 毫秒重新创建一次位图??
    猜你喜欢
    • 2014-01-23
    • 2011-05-23
    • 2018-02-12
    • 2011-11-07
    • 2012-11-05
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    相关资源
    最近更新 更多