Android:有效地管理位图arraylist而不会导致OutOfMemory异常

时间:2015-10-28 10:38:08

标签: java android bitmap android-canvas android-bitmap

我在android中实现了一本速写本。在这里我添加了一个画布。为了显示用户有多个页面,当用户点击下一页时,我将当前在画布上的位图保存到位图ArrayList 并清除画布以获取新位图。我将整个ArrayList一起保存到图像文件中(工作正常)。

问题是,在我的应用中,用户可以使用下一个和上一个按钮移动到之前绘制的位图,在这里我做了我从位图 ArrayList的即可。这就是我使用 Bitmap ArrayList 的原因。问题是,在创建了几页之后,如30页我的应用程序崩溃了,说 OutOfMemory异常

有人能建议一种有效的方法来实现我想要实现的目标,这样用户可以根据需要创建任意数量的页面并仍然来回导航?

以下是保存到位图arraylist

的代码
public void bitArrayStore(int k) {

        if (drawView.canvasBitmap.sameAs(drawView.emptyBitmap)) {
            flag = true;
        } else {

            try {
                if (flag1 == false) {
                    drawView.buildDrawingCache();
                    drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
                    bitmaps.set(k, Bitmap.createBitmap(drawView.getDrawingCache()));

                } else {
                    bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));
                    flag1 = false;
                }
            } catch (IndexOutOfBoundsException e) {
                bitmaps.add(k, Bitmap.createBitmap(drawView.getDrawingCache()));

            }
            drawView.destroyDrawingCache();

        }

当用户点击上一个或下一个按钮时,这是我用于重绘到画布的代码

public void redraw(ArrayList<Bitmap> bits, int i) {
        try {

                drawCanvas.drawBitmap(bits.get(i), 0, 0, canvasPaint);
                invalidate();


        }catch (NullPointerException e){
            Log.w("DrawingApp","Exception");
        }
    }

以下是onClickListeners

中下一个和上一个按钮的代码
if (v.getId() == R.id.previousbtn) {
            PageNoLayout.setVisibility(View.VISIBLE);
            hideDrawer(colorNsize);
            hideDrawer(eraserDrawer);
            try {
                bitArrayStore(j);
                drawView.startNew();
                j--;
                if (bitmaps.size() > j) {
                    drawView.redraw(bitmaps, j);
                }
            } catch (IndexOutOfBoundsException e) {
                j = 0;
                try {
                    drawView.redraw(bitmaps, j);
                } catch (IndexOutOfBoundsException e1) {
                    drawView.startNew();
                }
            }
            pageNo.setText(String.valueOf(j+1));
            flag = false;
        } else if (v.getId() == R.id.nextbtn) {
            PageNoLayout.setVisibility(View.VISIBLE);
            hideDrawer(colorNsize);
            hideDrawer(eraserDrawer);
            if (j < 50) {
                bitArrayStore(j);
                if (flag == false) {
                    j++;
                }
                if (bitmaps.size() > j) {
                    drawView.startNew();
                    drawView.redraw(bitmaps, j);
                } else {
                    drawView.startNew();
                }
                flag = false;
            } else {
                Snackbar.make(v, "Reached page limit. Please save and start new note", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
            pageNo.setText(String.valueOf(j+1));


        }

2 个答案:

答案 0 :(得分:0)

您应该使用像ViewPager这样的组件来管理加载/卸载页面的过程,因此您只需要在内存中显示要显示的页面。

否则你可以自己实现相同的逻辑。

希望这有帮助。

答案 1 :(得分:0)

请勿将Bitmap保存在ArrayList中。将它们保存在沙箱内部存储器或缓存中(通过getCacheDir())。当您按下一个或上一个时,您需要解码文件中的位图并通过其中一种解码方法加载它:BitmapFactory.decode()

您可以在ArrayList中保存文件路径,以便跟踪NextPrevious

此外,BitmapFactory.decode()可能会占用一段时间,如果您希望用户交互良好,您可以提前解码一对(仅几个)Bitmap,可能是异步的。完成Bitmap.recycle()后,请务必致电bitmap,然后转到下一个。