Java OutOfMemoryError с использованием изображения Picasso

Я пытаюсь загрузить изображение в ImageView и получаю OutOfMemoryError. Изображение отображается динамически в зависимости от конкретного представления в ViewPager. Однако после того, как я продолжаю прокручивать ViewPager, изображение в конечном итоге не загружается и вызывает ошибку OutOfMemoryError.

Обратите внимание, что у меня есть 4 View в ViewPager, и приложение, кажется, вылетает на View 2. Я предполагаю, что изображение просто слишком велико по размеру, но у меня сложилось впечатление, что Пикассо обрабатывает соответственно:

Код Пикассо:

Picasso.with(getActivity())
    .load(mImageURL)
    .fit()
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_CACHE)
    .into((ImageView) rootView.findViewById(R.id.comments_image));

XML

<ImageView
    android:id="@+id/comments_image"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight=".525"
    android:background="@color/black">
</ImageView>

Ошибка

java.lang.OutOfMemoryError: Failed to allocate a 5074572 byte allocation with 132096 free bytes and 129KB until OOM
     at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
     at android.graphics.Bitmap.nativeCreate(Native Method)
     at android.graphics.Bitmap.createBitmap(Bitmap.java:812)
     at android.graphics.Bitmap.createBitmap(Bitmap.java:789)
     at android.graphics.Bitmap.createBitmap(Bitmap.java:756)
     at android.graphics.drawable.VectorDrawable$VectorDrawableState.createCachedBitmapIfNeeded(VectorDrawable.java:713)
     at android.graphics.drawable.VectorDrawable.draw(VectorDrawable.java:280)
     at com.squareup.picasso.PicassoDrawable.draw(PicassoDrawable.java:105)
     at android.widget.ImageView.onDraw(ImageView.java:1176)
     at android.view.View.draw(View.java:15231)
     at android.view.View.updateDisplayListIfDirty(View.java:14167)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.draw(View.java:15234)
     at android.view.View.updateDisplayListIfDirty(View.java:14167)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.support.design.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1131)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.draw(View.java:15234)
     at android.support.v4.view.ViewPager.draw(ViewPager.java:2341)
     at android.view.View.updateDisplayListIfDirty(View.java:14167)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.support.v4.widget.DrawerLayout.drawChild(DrawerLayout.java:1373)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.updateDisplayListIfDirty(View.java:14162)
     at android.view.View.getDisplayList(View.java:14189)
     at android.view.View.draw(View.java:14959)
     at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
     at android.view.View.draw(View.java:15234)
     at android.widget.FrameLayout.draw(F

person tccpg288    schedule 08.06.2016    source источник
comment
Какое разрешение изображения?   -  person Vucko    schedule 09.06.2016
comment
Я знаю, что это 359,2 КБ и что это просто слишком много, однако я надеялся понять, как Пикассо может сжать, чтобы предотвратить эту ошибку. Изображение находится здесь: s3.amazonaws.com/fan-polls/Durant.jpg < / а>   -  person tccpg288    schedule 09.06.2016
comment
Как я понял недавно, это больше связано с разрешением, чем с размером. Я плохо знаком с Пикассо, хотя слышал о нем. Надеюсь, кто-то другой сможет помочь вам лучше.   -  person Vucko    schedule 09.06.2016


Ответы (2)


Вы сделали android: largeheap = "true" в своем самом манифестном файле?

<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="MyApplication"
    android:largeHeap="true"*
    android:logo="@drawable/logo_for_up"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme" >
</application>
person Vivek Faldu    schedule 09.06.2016
comment
Что это на самом деле делает, не могли бы вы помочь мне понять, прежде чем я буду реализовывать это? - person tccpg288; 09.06.2016
comment
Приложения, работающие на уровне API 11+, могут иметь android: largeHeap = true в элементе ‹application› в манифесте для запроса большего, чем обычно, размера кучи, а getLargeMemoryClass () в ActivityManager сообщит вам, насколько велика эта куча. - person Vivek Faldu; 10.06.2016
comment
Однако нет гарантии, насколько большой будет большая куча. Пользователь будет воспринимать ваш запрос большой кучи, потому что он заставит другие их приложения из ОЗУ завершать процессы других приложений, чтобы освободить системную оперативную память для использования вашей большой кучей. - person Vivek Faldu; 10.06.2016
comment
Используйте скольжение и даже не утруждайте себя большой кучей. Также ... использование большой кучи влияет на сборщик мусора, поэтому приложение будет работать медленнее. - person Christophe Chenel; 12.11.2018

Я предлагаю вам использовать Glide, поскольку он разработан для работы на недорогом (и худшем оборудовании) устройства по умолчанию.

Большая разница между Picasso и Glide заключается в том, что формат Glide по умолчанию - RGB_565, тогда как ARGB_8888 Пикассо. Как вы можете видеть ниже, выполнение той же работы требует на 50% меньше памяти, чем Picasso.

Стоимость памяти

Тем не менее, если вы не готовы изменять свою библиотеку, вы можете попробовать изменить размер изображения в конструкторе Picasso, используя метод .resize(int, int).

person Lucas Albuquerque    schedule 09.06.2016
comment
Я заметил, что ошибка возникает в эмуляторе Samsung, но эмулятор HTC, который я использую, не имеет проблем. - person tccpg288; 09.06.2016
comment
Я заинтересован в установке максимального размера 100 КБ, есть идеи, как я это сделаю? - person tccpg288; 09.06.2016
comment
Я не думаю, что есть способ добиться этого с помощью Picasso, поскольку ему нужно будет вычислить, какой размер (комбинация ширины и высоты) даст максимум 100 КБ в вашей памяти. - person Lucas Albuquerque; 09.06.2016
comment
Я точно не могу использовать другую библиотеку. Я использую Picasso для некоторой модификации изображений, и это важно для моего приложения. - person tccpg288; 11.06.2016
comment
Но я просил вас не только изменить вашу библиотеку. Прочтите абзац Still ... - person Lucas Albuquerque; 11.06.2016
comment
Тем не менее, если нет другого способа оптимизировать использование памяти с помощью этой библиотеки, вопрос следует закрыть. - person Lucas Albuquerque; 11.06.2016
comment
Я переключаюсь с Picasso на Glide. Я даже смог убрать использование большой кучи. Работает как часы. - person Christophe Chenel; 12.11.2018