2015-10-28 34 views
0

我在android中实现了一个sketch-book。在这我添加了一个画布。为了显示用户有多个页面,当用户点击下一页时,我将当前在画布上的位图保存到位图ArrayList并清除画布以获取新的位图。我将整个ArrayList一起保存到图像文件中(这很好用)。Android:高效管理位图ArrayList,不会导致OutOfMemory异常

的问题是,在我的应用程序的用户是能够移动使用下一页之前绘制的位图和以前按钮,在这里,我做到了从位图的ArrayList我重绘位图。这就是为什么我使用位图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)); 


     } 
+1

要做到这一点的唯一方法是将位图保存在磁盘(PNG或JPG)中,然后重新加载。位图使用大量内存,如果您尝试在内存中使用太多内存,则会耗尽内存,这很简单。 – Budius

+0

我想通了。但我无法想出一个替代方案。这就是我问的原因。感谢您的回应。就像你说的,如果我保存到磁盘中,我将如何知道以前的文件是什么或下一个文件是什么?你能帮我解决这个困惑吗? @Budius – JCoder

+0

你只需要记住'pager number'和'file path'之间的关系。你可以有一个标准的命名约定,'page_X.png',或者放入一个SQLite数据库,有一个'ArrayList ',写入共享首选项。 – Budius

回答

0

您应该使用组件就像一个ViewPager一样,可以根据需要管理加载/卸载页面的过程,因此您只能在内存中显示将要显示的页面。

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

希望这会有所帮助。

0

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

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

此外,BitmapFactory.decode()可能需要一段时间,如果您希望用户互动良好,您可能会提前解码几个(只是几个)Bitmap,可能是异步解码。确保您在完成bitmap之后致电Bitmap.recycle()并转到下一个。