2014-11-14 2 views
14

Я использую библиотеку 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) 
+2

«Я думаю, что это не способ что-то большое или тяжелые "- эти изображения огромны *. Файлы изображений, такие как PNG и JPEG, сжимаются; ваше пространство кучи для этих изображений будет несколько MB за штуку. – CommonsWare

+0

@CommonsWare Я сказал, что с учетом изображений в камерах в 20-30 раз больше. Спасибо, что указал мне в правильном направлении. Должен ли я беспокоиться или игнорировать эту проблему, поскольку приложение работает нормально. –

+2

«Я сказал, что с учетом того, что изображения в камерах в 20-30 раз больше, чем у них» - вы не можете одновременно загружать 25-30 изображений камеры с полным разрешением в память. «Приложение работает нормально» - нет, ваше приложение рушится, о чем свидетельствует трассировка вашего стека. Вам нужно, чтобы Picasso уменьшал изображение до размера, соответствующего вашему 'GridView', например, путем цепочки вызова' fit() 'в вашем коде, показанном выше. – CommonsWare

ответ

25

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

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

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

+0

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

+1

@AdeelAhmad: Хммм ... по какой-то причине я думал, что 'fit()' сделал 'resize()', но я, вероятно, неправильно помню. Рад, что он работает на вас! – CommonsWare

+3

Я только что проверил источник, fit() действительно вызывает изменение размера() - сразу, если цель имеет размер или после того, как цель имеет размер. – enl8enmentnow

0

Если нравится

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

Часы с .Поставить (!)

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

+0

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

1

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

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

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

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

TLDR:

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

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

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