2016-06-25 3 views
0

Во-первых, я понимаю вопросы относительно java.lang.OutOfMemoryError и растровые изображения уже заданы несколько раз раньше. Я также проверил страницу Displaying Bitmaps Efficiently.java.lang.OutOfMemoryError при преобразовании более 100 строк в байт-массивы

Мой случай использования:

Я храню два разных размера Bitmaps как строки в базе данных SQLite. Первый размер битмапов составляет 50% ширины экрана, а второй размер - 100% от ширины экрана.

Я использую RecyclerView, который отображает изображения в ImageViews, которые являются либо 50%, либо 100% ширины экрана, поэтому загружаемые растровые изображения не больше, чем они должны быть, и они должны соответствовать размерам до изображения извлекаются из базы данных.

Я также загружаю растровые изображения с помощью AsyncTask.

У меня есть более 180 различных элементов в RecyclerView, поэтому я создаю в общей сложности более 360 битмапсов (т. Е. Числовое изображение * theDifferentSizesOfEachImage). Я coverting строковой версии изображений в массив байт с помощью этого кода: byte [] byteArray = Base64.decode(encodedString, Base64.DEFAULT);

Проблемы

Деятельности удалась загрузить более около 170 различных изображений без encurring в java.lang.OutOfMemoryError, если я не перезапущен же Действия (например, загрузите Activity, затем заново создайте Activity, щелкнув ее снова в навигационном ящике, а затем повторите этот процесс) и понесли java.lang.OutOfMemoryError, преобразовывая строки в байтовые массивы.

Я преобразование массива в Bitmap, используя библиотеку Glide, используя следующий код:

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

Мой вопрос в ореховой скорлупе

Как избежать java.lang.OutOfMemoryError происходит в то время как Я преобразовываю строки в байтовые массивы?

Примечание

После создания растрового изображения с помощью Glide я звоню рециркуляцию() на данном Bitmap, а затем установить его в null.

Я также уже использую android:largeHeap="true" в моей Android манифеста

Заранее спасибо

Редактировать

Вот как я создаю Bitmap строк:

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 (Context контекст, внутр м) {

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; 
} 

Теперь у вас есть файл, и теперь вы можете просто сохранить путь к файлу в базе данных, и когда его нужно всегда можно получить ваш файл из хранилища с помощью скольжения. Это также сделает вашу базу данных быстрой для запросов.

Таким образом, вам не нужны какие-либо изменения в граде или в другом месте. Попробуй это.

+0

Спасибо за ваш ответ. Я либо попытаюсь сохранить изображения в виде файлов как массивы байтов, если это решит 'java.lang.OutOfMemoryError'. Считаете ли вы, что сохранение изображений в файлах и преобразование файлов в изображения более эффективно с точки зрения памяти, чем сохранение изображений в виде массивов байтов в столбце BLOB в базе данных SQLIite, а затем преобразование этих байтовых массивов в растровые изображения? –

+0

Да, сэр, вы также не конвертируете какой-либо файл в изображение. Изображение, сохраненное в хранилище, само является файлом. Теперь вы просто дадите библиотеке glide прямой путь к вашему файлу и оставите кеширование и показ изображения в вашем представлении для скольжения, которое выполняется очень эффективно. Просто дайте ему шанс и практиковать это решение всегда. То, что вы делали раньше, это просто пустая трата памяти. Сохраняя изображения как файлы в папке приложений, вы не обнаружите, что галерея работает так, как вы этого хотите. –

+0

Спасибо за информацию. Я попробую сохранить изображения в виде файлов, и если это решит 'java.lang.OutOfMemoryError', тогда я приму ваш ответ –

 Смежные вопросы

  • Нет связанных вопросов^_^