Recycliewiew мучительно медленно загружает кешированные изображения из Picasso

Я реализовал RecyclerView, который содержит в основном изображения, которые загружаются через Picasso. Моя проблема заключается в том, что как только я прокручу вниз или вверх по виду, изображение заполнителя появится примерно на ок. Секунду, прежде чем он будет заменен фактическим изображением. Он прокручивается очень плавно, но практически непригодным для использования. Это происходит каждый раз, когда что-то прокручивается с экрана.

Picasso явно кэширует изображения на диск, так как они загружаются быстрее, чем начальное время загрузки, но они, безусловно, мгновенно перезагружаются из кеша. Что я сделал неправильно?

Мой код адаптера:

public class ExploreAdapter extends RecyclerView.Adapter<ExploreAdapter.ExploreViewHolder> { private List<ExploreItem> exploreItemList; private Context mContext; private int deviceWidth = PrefUtils.getDeviceWidth(); public ExploreAdapter(Context context, List<ExploreItem> exploreItemList){ this.mContext = context; this.exploreItemList = exploreItemList; } @Override public int getItemCount(){ return exploreItemList.size(); } @Override public void onBindViewHolder(ExploreViewHolder exploreViewHolder, int i){ ExploreItem item = exploreItemList.get(i); exploreViewHolder.getvTitle().setText(item.getTitle()); exploreViewHolder.getvUsername().setText(item.getUsername()); exploreViewHolder.getvNumLikes().setText(item.getNbOfLikes()); Picasso.with(mContext).load(item.getMediaLocation().trim()) .resize(deviceWidth, deviceWidth) .centerCrop() .placeholder(R.drawable.profile_background) .into(exploreViewHolder.getvImage()); Picasso.with(mContext).load(item.getUserProfilePicUrl().trim()) .placeholder(R.drawable.profile_picture) .into(exploreViewHolder.getvProfilePic()); } @Override public ExploreViewHolder onCreateViewHolder(ViewGroup viewGroup, int i){ View itemView = LayoutInflater. from(viewGroup.getContext()). inflate(R.layout.explore_item, viewGroup, false); return new ExploreViewHolder(itemView); } public static class ExploreViewHolder extends RecyclerView.ViewHolder{ private TextView vTitle, vUsername, vNumLikes; private SquareImage vImage; private ImageView vProfilePic; public ExploreViewHolder(View v){ super(v); this.vTitle = (TextView) v.findViewById(R.id.explore_item_title); this.vUsername = (TextView) v.findViewById(R.id.explore_item_username); this.vNumLikes = (TextView) v.findViewById(R.id.explore_item_number_likes); this.vImage = (SquareImage) v.findViewById(R.id.explore_item_image); this.vProfilePic = (ImageView) v.findViewById(R.id.explore_item_profile_picture); } public TextView getvTitle() { return vTitle; } public TextView getvUsername() { return vUsername; } public ImageView getvProfilePic() { return vProfilePic; } public SquareImage getvImage() { return vImage; } public TextView getvNumLikes() { return vNumLikes; } public void setvImage(SquareImage vImage) { this.vImage = vImage; } public void setvNumLikes(TextView vNumLikes) { this.vNumLikes = vNumLikes; } public void setvProfilePic(ImageView vProfilePic) { this.vProfilePic = vProfilePic; } public void setvTitle(TextView vTitle) { this.vTitle = vTitle; } public void setvUsername(TextView vUsername) { this.vUsername = vUsername; } } } 

Любая помощь приветствуется.

Solutions Collecting From Web of "Recycliewiew мучительно медленно загружает кешированные изображения из Picasso"

Настройка параметров recyclerView, как показано ниже, разрешила мою проблему заикания:

 recyclerView.setHasFixedSize(true); recyclerView.setItemViewCacheSize(20); recyclerView.setDrawingCacheEnabled(true); recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); 

Я надеюсь, что это поможет кому-то еще.

Используйте fit() .

 Picasso.with(context) .load(file) .fit() .centerCrop() .into(imageView); 

Функция fit() фактически изменяет размер изображения для соответствия imageView . Это не загружает полное изображение и не сглаживает прокрутку.

Я недавно столкнулся с этой проблемой, и да, вы правы. Picasso – хорошая библиотека для показа изображений с SD-карты, но у нее есть некоторые проблемы с кешем, если вы извлекаете изображения в Интернете, поэтому вы видите изображение владельца места при прокрутке. Я пробовал разные вещи, и проблема не была решена.

Существует альтернативная библиотека, т.е. «AQuery», которая очень хороша для извлечения и кэширования изображений из сети.

http://code.google.com/p/android-query/

Основными преимуществами AQuery / Android Query являются то, что вы можете очистить кеш, не задерживаться во время прокрутки и довольно эффективно для кэширования изображений и не показывать изображения держателей места во время прокрутки.

Я решил проблему, удалив picaaso и используя Aquery. Это просто замена одной строки, и вы закончили свою проблему.

 (new AQuery(mContext)).id(exploreViewHolder.getvProfilePic()).image(item.getUserProfilePicUrl().trim(), true, true, device_width, R.drawable.profile_background, aquery.getCachedImage(R.drawable.profile_background),0); 

Кроме того, вы можете легко перейти от picasso к AQuery, поскольку нет такой вещи, которая доступна в picasso, но не в AQuery, и синтаксис почти такой же. Поэтому я бы рекомендовал вам использовать AQuery, пока это не будет зафиксировано в picasso.

Я смешал ответ с @ergunkocak и @Mangesh Ghotage, используя это отлично:

 recyclerView.setHasFixedSize(true); recyclerView.setItemViewCacheSize(20); recyclerView.setDrawingCacheEnabled(true); 

И это на каждом изображении:

 Picasso.with(context) .load(file) .fit() .into(imageView); 

Кроме того, вы можете настроить Picasso на использование одного экземпляра:

 Picasso.setSingletonInstance(picasso); 

И, наконец, включение индикаторов кеша даст вам понять, что происходит:

 Picasso .with(context) .setIndicatorsEnabled(true); 

Побробнее о Пикассо

Я не могу проверить правильность этого решения, но я столкнулся с этой проблемой и подошел к ней по этой идее:

 @Override public void onBindViewHolder(ViewHolder viewHolder, final int i) { ... if(mImageView.getDrawable == null()){ Picasso.with(context) .load(path) .error(errorResId) .tag(tag) .into(mImageView); } ... 

}

Предполагается запретить Пикассо загружать что-либо, если ImageView не будет отображаться.

Picasso автоматически кэширует изображения на двух уровнях:

  • Дисковый кеш (это на самом деле НЕ на пикассо, а на сетевом уровне, который использует пикассо)
  • Кеш памяти

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

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

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

См. Здесь: Android Picasso Настройка размера LruCache

Но я советую ПРОТИВ увеличения размера кэша памяти, если вы действительно не переопределяете изображения до фактического размера, который вы используете.

Я думаю, что проблема с вашим кодом заключается в следующем:

 .resize(deviceWidth, deviceWidth) 

Вы уверены, что вам действительно нужен образ такого размера? Что вы храните в PrefUtils? Он обновляется, когда устройство вращается? (Пейзаж против портрета)

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

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

Просто используйте атрибут noPlaceholder .