2016-06-25 78 views
0

首先,我瞭解有關java.lang.OutOfMemoryError的問題,並且之前已經多次提到Bitmap。我也檢查了Displaying Bitmaps Efficiently頁面。將100多個字符串轉換爲字節數組時,java.lang.OutOfMemoryError

我的使用情況:

我存儲兩個不同尺寸的位圖作爲字符串中的SQLite數據庫。位圖的第一個大小是屏幕寬度的50%,第二個大小是屏幕寬度的100%。

我正在使用一個RecyclerView,它在ImageViews中顯示50%或100%的屏幕寬度的圖像,因此正在加載的的位圖不會比他們需要的大,並且它們在圖像從數據庫中檢索。

我也使用AsyncTask加載位圖。

我在RecyclerView中有超過180個不同的項目,所以我總共創建了超過360個Bitmaps(即numberOfimages * theDifferentSizesOfEachImage)。我從這個代碼coverting的圖像轉換成字節數組的字符串版本:byte [] byteArray = Base64.decode(encodedString, Base64.DEFAULT);

的問題

的活性爲能夠圍繞170個不同的圖像加載比沒有encurring的java.lang.OutOfMemoryError,除非我重新啓動同活動(例如加載活動,然後通過在導航抽屜中再次單擊並重復該過程來重新創建活動),並在將字符串轉換爲字節數組的同時發生java.lang.OutOfMemoryError

我使用滑翔庫使用下面的代碼的字節數組轉換爲位圖:

Bitmap bitmap = Glide.with(context).load(byteArray).asBitmap() 
.dontTransform().dontAnimate().skipMemoryCache(true) 
.diskCacheStrategy(DiskCacheStrategy.NONE).into(-1, -1).get(); 

我概括地說

問題如何避免發生java.lang.OutOfMemoryError而我是否將字符串轉換爲字節數組?

注意

利用Glide我打電話循環()在給定的位圖創建位圖,然後將其設置爲null後。

我也已經在我的Android清單

在此先感謝使用android:largeHeap="true"

編輯

這裏是我正在創建中位圖字符串:

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     bitmap.compress(Bitmap.CompressFormat.WEBP,100, baos); 
     byte [] b =baos.toByteArray(); 
    String bitmapString = Base64.encodeToString(b, Base64.DEFAULT); 
+0

爲什麼不在存儲之前壓縮它... –

+0

感謝您的回覆。如果你指的是壓縮位圖,我已經這樣做了,我編輯了我的問題,你可以看到我如何壓縮位圖,然後將它們轉換爲字符串 –

+0

「我將兩個不同大小的位圖存儲爲SQLite數據庫中的字符串」 - - 爲什麼?將它們作爲文件存儲,並將文件名存儲在數據庫中。或者,將它們存儲爲BLOB列,以至少消除「String」轉換。 – CommonsWare

回答

1

什麼我會建議你放棄你的方法,這將不適用於大量的圖像和你已經在你的線程上處理很多工作。不應該像在sqllite中那樣存儲圖像。 您應該將位圖轉換爲具有唯一名稱的文件,或者可以相同(取決於您的用例),然後您可以將該文件保存在應用程序目錄中並將文件路徑保存在數據庫中。這裏有一些代碼可以幫助你。

File pictureFile = getOutputMediaFile(getActivity(), MEDIA_TYPE_IMAGE); 
     if (pictureFile == null) { 
      return; 
     } 
     Bitmap bitmap =BitmapFactory.decodeByteArray(data,0,data.length); 

      FileOutputStream fos = new FileOutputStream(pictureFile); 
      bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); 
      fos.flush(); 
      fos.close(); 

私人文件getOutputMediaFile(上下文的背景下,INT M){

File mediaStorageDir = context.getFilesDir(); 

    if (!mediaStorageDir.exists()) { 
     if (!mediaStorageDir.mkdirs()) { 
      Log.d("Fade", "failed to create directory"); 
      return null; 
     } 
    } 
    // Create a media file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") 
      .format(new Date()); 

    File mediaFile=new File(mediaStorageDir.getPath()+File.separator 
       + "IMG_" + timeStamp + ".JPG"); 

    return mediaFile; 
} 

現在你有文件,現在你可以在數據庫中存儲的文件路徑和它在需要的時候,你總是可以得到您的文件從存儲使用滑翔。這也會使你的數據庫查詢更快。

這樣你就不需要在gradle或其他地方做任何改變。嘗試這個。

+0

感謝您的回覆。如果將解決'java.lang.OutOfMemoryError',我會嘗試將圖像保存爲字節數組。您認爲將圖像保存爲文件,然後將文件轉換爲圖像比將圖像保存爲SQLIite數據庫的BLOB列中的字節數組,然後將這些字節數組轉換爲位圖更有效? –

+0

是的,先生,你也沒有將任何文件轉換成圖像。保存在存儲器中的圖像本身就是一個文件。您現在要給滑行庫提供文件的直接路徑,並將視圖中的圖像緩存和顯示保持爲非常高效的滑行。只要給它一個機會,並始終練習這個解決方案。你之前在做什麼只是浪費記憶。通過將圖像保存爲應用程序文件夾內的文件夾不會泄露它,因此圖庫就像你想要的一樣工作。 –

+0

感謝您的信息。我會嘗試將圖像保存爲文件,如果解決了'java.lang.OutOfMemoryError',那麼我會接受你的答案 –

相關問題