Библиотека Пикассо - вне памяти

Я использую библиотеку Picasso последней версии 2.4.0 в своем приложении для загрузки и кэширования изображений. Примерно 25-30 изображений размером 300 КБ-400 КБ каждый. Я думаю, что это не что-то большое или тяжелое.

Несмотря на то, что приложение работает нормально, я получаю выделения из памяти в своем логарифме. Может ли кто-нибудь объяснить, почему это происходит?

Код для загрузки изображений в адаптере GridView:

Picasso.with(mContext).load(getUrl()).placeholder(R.drawable.placeholder)
            .into(viewholder.image);

Вот мой вывод Logcat:

I/dalvikvm-heap(11142): Grow heap (frag case) to 53.860MB for 2720016-byte allocation
I/dalvikvm-heap(11142): Forcing collection of SoftReferences for 3265936-byte allocation
E/dalvikvm-heap(11142): Out of memory on a 3265936-byte allocation.
I/dalvikvm(11142): "Picasso-/images/posters/34.71.jpg" prio=5 tid=18 RUNNABLE
I/dalvikvm(11142):   | group="main" sCount=0 dsCount=0 obj=0x4283f248 self=0x60a47830
I/dalvikvm(11142):   | sysTid=11196 nice=10 sched=0/0 cgrp=apps/bg_non_interactive I/dalvikvm(11142):   | state=R schedstat=( 2070202497 1858185620 3947 ) utm=172 stm=35 core=3
I/dalvikvm(11142):   at android.graphics.Bitmap.nativeCreate(Native Method)
I/dalvikvm(11142):   at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
I/dalvikvm(11142):   at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
I/dalvikvm(11142):   at android.graphics.Bitmap.createBitmap(Bitmap.java:636)
I/dalvikvm(11142):   at com.squareup.picasso.BitmapHunter.transformResult(BitmapHunter.I/dalvikvm(11142):   at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:168)
I/dalvikvm(11142):   at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:111)
I/dalvikvm(11142):   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390I/dalvikvm(11142):   at java.util.concurrent.FutureTask.run(FutureTask.java:234)
I/dalvikvm(11142):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.I/dalvikvm(11142):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.I/dalvikvm(11142):   at java.lang.Thread.run(Thread.java:841)
I/dalvikvm(11142):   at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:408)
I/dalvikvm-heap(11142): Forcing collection of SoftReferences for 3265936-byte allocation
E/dalvikvm-heap(11142): Out of memory on a 3265936-byte allocation.
I/dalvikvm(11142): "Picasso-/images/posters/34.71.jpg" prio=5 tid=17 RUNNABLE
I/dalvikvm(11142):   | group="main" sCount=0 dsCount=0 obj=0x42841b88 self=0x5ec91f90
I/dalvikvm(11142):   | sysTid=11183 nice=10 sched=0/0 cgrp=apps/bg_non_interactive I/dalvikvm(11142):   | state=R schedstat=( 2050467088 1713164574 3713 ) utm=172 stm=32 core=3
I/dalvikvm(11142):   at android.graphics.Bitmap.nativeCreate(Native Method)
I/dalvikvm(11142):   at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
I/dalvikvm(11142):   at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
I/dalvikvm(11142):   at android.graphics.Bitmap.createBitmap(Bitmap.java:636)
I/dalvikvm(11142):   at com.squareup.picasso.BitmapHunter.transformResult(BitmapHunter.I/dalvikvm(11142):   at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:168)
I/dalvikvm(11142):   at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:111)
I/dalvikvm(11142):   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390I/dalvikvm(11142):   at java.util.concurrent.FutureTask.run(FutureTask.java:234)
I/dalvikvm(11142):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.I/dalvikvm(11142):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.I/dalvikvm(11142):   at java.lang.Thread.run(Thread.java:841)
I/dalvikvm(11142):   at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:408)

Ответы

Ответ 1

В исходном коде загружалось полное изображение, загружалось полное изображение в память, а затем Android масштабировал изображение до вашего ImageView.

В этом случае вам не нужно полное изображение в памяти - вам нужно что-то ближе по размеру к тому, что есть ImageView.

fit() на Пикассо справляется с этим. Он использует inSampleSize на BitmapFactory.Options для уменьшения размера изображения, поскольку он загружается в память, чтобы получить что-то вокруг размера ImageView, позволяя оттуда отображать на нем шкалу Android. Это значительно уменьшит объем памяти каждого изображения, особенно в зависимости от того, насколько большой из ImageView вы используете.

Ответ 2

Остерегайтесь .fit()!

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

Ответ 3

Все остальные ответы звучат хорошо при упоминании .fit().

Я думаю, что может быть интересно отметить недостаток .fit, хотя:

fit() измеряет размеры целевого ImageView и внутренне использует resize(), чтобы уменьшить размер изображения до размеров ImageView. Есть две вещи, которые нужно знать о fit(). Во-первых, вызов fit() может задержать запрос изображения, поскольку Picasso нужно будет ждать, пока не будет измерен размер ImageView. Во-вторых, вы можете использовать fit() с ImageView в качестве цели (мы рассмотрим другие цели позже).

Преимущество заключается в том, что изображение имеет наименьшее возможное разрешение, не влияя на его качество. Более низкое разрешение означает меньшее количество данных, которые должны храниться в кеше. Это может значительно уменьшить влияние изображений в области памяти вашего приложения. В общем, если вы предпочитаете меньшее влияние памяти на несколько более быстрое время загрузки, fit() - отличный инструмент.

TL;DR:

  • Может использоваться только с объектами ImageView
  • Может замедлить загрузку.

Источник: https://futurestud.io/tutorials/picasso-image-resizing-scaling-and-fit

Ответ 4

Вам понравится

Picasso.with(mContext).load(getUrl()).fit().placeholder(R.drawable.placeholder)
        .into(viewholder.image);