2016-01-26 2 views
4

Я пытаюсь сделать recyclerview с gifs. Все отлично, но фреска не кэширует gif. После прокрутки списков рециркуляции и прокрутки вверх снова gifs загружаются еще раз. Я предположил, что их нужно кэшировать и загружать немного быстрее. Раньше я использовал ION library. Загрузка была быстрее и не имела проблемы с кешем. Мне пришлось изменить lib, потому что у него есть некоторая проблема с декодированием gif, описанная here. Текущее решение выглядит так:Кэширование gifs в fresco

//for default initial in application class 

Fresco.initialize(this); 
//I have also tried to change DiskCacheConfig and ImagePipelineConfig params. 
//Without any positive result 

//for recyclerview on onBindViewHolder  
GenericDraweeHierarchy hierarchy = holder.draweeView.getHierarchy(); 
Uri uri = Uri.parse(path); 
hierarchy.setPlaceholderImage(R.drawable.img_bg); 
Logger.e(check(uri) + " " + uri.toString()); 
DraweeController controller = Fresco.newDraweeControllerBuilder().setUri(uri) 
      .setAutoPlayAnimations(true).build(); 
    holder.draweeView.setController(controller); 

//for method which show cached uri images in imagepipeline 
public static boolean check(Uri uri) { 
    ImagePipeline imagePipeline = Fresco.getImagePipeline(); 
    return imagePipeline.isInBitmapMemoryCache(uri); 
} 
//... all the time log shows "false + gif url" 

Я не видел никакой информации о не кешировании анимированных изображений. Существует информация о не поддерживаемой постобработке изображений для анимаций, но это все об этом. Как правильно кешировать gif?

Редактировать: Это похоже на анимацию кеш-фрески, потому что ниже метод возвращает true для перезагруженных gif.

public static boolean isImageDownloaded(Uri loadUri) { 
    if (loadUri == null) { 
     return false; 
    } 
    CacheKey cacheKey = DefaultCacheKeyFactory.getInstance() 
      .getEncodedCacheKey(ImageRequest.fromUri(loadUri)); 
    return ImagePipelineFactory.getInstance().getMainDiskStorageCache().hasKey(cacheKey) 
      || ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache() 
        .hasKey(cacheKey); 
} 

ответ

0

Я столкнулся с аналогичной проблемой, оказывается, что Фреско правильно кэширование GIF изображений, но на самом деле это занимает время, чтобы декодировать и воспроизводить анимацию каждый раз, когда вы пролистать RecyclerView или любого другого вида вас» повторно используя. Однако, если вы используете gif-образ без анимации, изображение gif не «перезагружается» при прокрутке просмотра.

Поскольку у меня есть контроль над изображениями, отображаемыми внутри моего приложения. Я создаю 2 версии gif-изображений на своем сервере, первый из которых без анимации отображается внутри RecyclerView/ListView, а другой для отображения внутри действия «Просмотр медиа», когда пользователь нажимает на элемент в списке.

+0

Это не удовлетворительное решение. Я должен показать автозапущенную сетку gif. Когда вы посмотрите на приложение GIF Keyboard, вы увидите список/сетку gif с автозапускной анимацией. Он плавно прокручивается с приемлемым поведением кэша. Их решение должно быть уместным. – Nihilus13

+0

Должно быть уместно, но, к сожалению, я не могу понять, как они достигли эффективного кеша и плавного прокрутки. – Nihilus13

+0

Я использую фрески, чтобы загрузить gif и не анимировать ее. Когда прокрутка, я все еще получаю проблему –

1

Просто, чтобы сделать вещи немного более ясно, Фреско имеет 3 уровня кэш-памяти:

  • DiskCache - Сохраняет файлы изображений в их исходном формате. (Чтобы быть точным, если на версии Android, которая не поддерживает полностью webp изображений, они могут быть перекодированы в другой формат перед сохранением.)
  • EncodedMemoryCache - Кэш-память в памяти изображений в исходном закодированном формате. (Изображение хранится как байтовый массив исходных байтов , поскольку они хранятся на диске + некоторые дополнительные метаданные.)
  • BitmapMemoryCache - кэш памяти, состоящий в основном из растровых изображений Android. Растровые изображения являются декодированными изображениями, и каждый пиксель занимает 32 бита , что значительно больше, чем требуется при кодировании.

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

Теперь вернемся к анимированным изображениям. Это известное ограничение. Анимированные изображения не кэшируются в их декодированной форме, потому что это приведет к исчерпанию кеша битмапа (просто умножьте num_frames * width * height * 32bpp), и одно анимированное изображение может выселить все остальные изображения в кеше. Вместо этого они декодируются по требованию, и только несколько кадров, которые будут отображаться дальше, хранятся в кратковременном кэше.

У нас есть планы по улучшению анимации, хотя я не могу предоставить никаких временных оценок.

+1

Я просто хочу знать, как кэшировать и показывать первый кадр gif –

+0

Возможно, вам необходимо уточнить в исходном вопросе, что вас интересует только первый кадр. – plamenko

0

Фреска, они в основном сфокусированы на низких размерах gif.Я пробовал с низким gifs в recycleview, кеширование работает отлично. Если вы используете GIF с высоким разрешением, им требуется большое потребление памяти для декодирования и кеширования. может превышать размер кучи. поэтому они декодируются по требованию, и только несколько кадров (которые должны отображаться) получают кеширование.

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

 ImageDecodeOptionsBuilder b = new ImageDecodeOptionsBuilder(); 
     b.setForceStaticImage(true); 
     ImageDecodeOptions imageDecodeOptions=new ImageDecodeOptions(b); 
     ImageRequest request = ImageRequestBuilder.newBuilderWithSource(animatedGifUri).setImageDecodeOptions(imageDecodeOptions).setLocalThumbnailPreviewsEnabled(true).build();