2015-10-28 32 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()並轉到下一個。