Рекомендации по использованию песочницы или кэширования для асинхронной загрузки изображений UITableView

Неделю назад Apple выпустила пример кода для ленивой загрузки изображений в UITableView. Я проверил это и внедрил в свой собственный UITableView (который является drawRect для быстрой прокрутки), чтобы увидеть, есть ли разница с тем, что я уже делал.

После реализации я не уверен, что лучше; новый код или то, что у меня уже было. Я не вижу большого улучшения скорости на моем 3GS.

Метод «песочницы»: лениво загружайте изображения, затем сохраняйте их в локальную папку tmp в «песочнице». Каждый раз, когда отображается ячейка, она ищет, находится ли уже изображение с таким именем файла в папке песочницы. Если это так, он извлекает изображение и отображает его, если нет, он продолжает загрузку, сохраняет его локально, а затем отображает его. Преимущество этого заключается в том, что изображения не будут пустыми при втором открытии приложения. Они уже будут загружены и готовы к показу.

Метод кэширования: это также лениво загружает изображения, однако теперь я включаю UIImage для каждого объекта в массиве, отображаемом в табличном представлении. Вместо того, чтобы сохранять изображение локально, я теперь загружаю изображение и помещаю его в массив для объекта. Теперь, вместо того, чтобы каждый раз проверять имя файла, он просто проверяет, использует ли UIImage != nil кэшированное изображение (или загружает, если nil).

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

Я предполагаю, что мой вопрос будет заключаться в том, должен ли я вообще возиться с кодом кэширования? Опять же, новый код не будет сразу загружать изображения при новом запуске, в то время как старый код на самом деле делает это, потому что он уже находится в песочнице. Поскольку я не использую изображения повторно, мне нужно загрузить много изображений (из песочницы или кеша), поэтому я не замечаю огромной разницы в скорости. На самом деле, на моем 3GS почти невозможно сказать, по-моему. Прокрутка не очень плавная, и я предполагаю, что это связано с большим количеством изображений, которые я не могу использовать повторно (разные изображения для каждой ячейки). Мне также интересно, станет ли метод песочницы работать медленнее, если, например, в папке будет более 1000 изображений, в конечном итоге он просматривает гораздо больше изображений, чем просто 100 или около того.

Я надеюсь, что я имею смысл. Я хотел быть довольно тщательным с деталями, и я рад дать больше деталей, если это необходимо.

Спасибо!


person runmad    schedule 23.11.2009    source источник
comment
Всем, кто читает это сейчас (поскольку это старый пост), я настоятельно рекомендую проверить встроенное кэширование изображений в AFNetworking или отличное расширение UIImageView/UIImage SDWebImage, которые обрабатывают кэширование и асинхронную загрузку.   -  person runmad    schedule 07.01.2013


Ответы (3)


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

В методе "песочницы" меня в первую очередь беспокоит не производительность, а использование дискового пространства. Пользователи не оценят, что вы заполняете их iPhone или iPod Touch ненужными файлами, особенно если все изображения не используются постоянно или если набор используемых изображений часто меняется. Не зная больше о вашем приложении, невозможно угадать, как часто будут загружаться эти кэшированные изображения.

Если вы тестируете локально на своем устройстве, возможно, вы находитесь в сети Wi-Fi. Я бы порекомендовал отключить Wi-Fi для части вашего тестирования, чтобы увидеть, как работают два подхода, когда вам нужно получить все изображения по сотовой сети. Я бы также рекомендовал попробовать найти более старое устройство (iPhone 3G или хуже), потому что 3GS на самом деле скрывает потенциальные проблемы с производительностью, которые могут раздражать пользователей старых устройств.

Я лично использовал метод LazyTableImages в своих приложениях много раз (при условии, что он не сильно изменился между WWDC09 и недавним «выпуском») и считаю, что это именно то, что мне нужно. Однако кэширование изображений на диске в моем случае не подходит, и вам не следует слишком сильно принимать во внимание мой анекдот — профилируйте свой собственный код и используйте результаты, которые он показывает.

Редактировать:

The obvious answer is that accessing an in-memory cache is going to be faster than accessing the filesystem, but of course the final word on that is left up to profiling. If the images are already in memory, they don't need to be read from flash and parsed by UIImage. The traditional tradeoff comes into play here though - in-memory caching vs. disk space.

Хотя для вас может быть быстрее хранить ваши изображения в памяти, вы должны быть очень уверены, что правильно обрабатываете предупреждения памяти в своем приложении (как вы и должны делать в любом случае!). В противном случае длительный период использования приведет к большому количеству изображений в вашем кеше в памяти и вызовет предупреждения о памяти, и если ваше приложение не создано для их обработки, в лучшем случае ваше приложение будет уничтожено ОС из-за нехватки ресурсов памяти.

person Bryan Henry    schedule 23.11.2009
comment
Спасибо за понимание. Ре. в песочнице он находится в папке tmp, поэтому его резервная копия не создается. Я также установил ограничение на 10 МБ и очистил его, если размер песочницы достигает 10 МБ+. Я использую тот же метод для ленивой загрузки изображений, в основном, поэтому меня не слишком беспокоит, будет ли быстрее фактическая загрузка изображений. Меня больше интересует, какой из двух быстрее с точки зрения производительности (кэширование или песочница). - person runmad; 23.11.2009

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

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

person bwinton    schedule 23.11.2009
comment
Я уже делаю загрузку, если не туда, то сохраняю, то загружаю из песочницы подход. Это просто с точки зрения песочницы изображения и его извлечения таким образом или помещения его в объект uiimage объекта. - person runmad; 23.11.2009

В обоих представленных вами подходах есть свои плюсы и минусы — я предлагаю использовать элементы обоих в вашем приложении.

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

Также лучше избегать изменения размера на лету, т. е. в ваших методах tableView:cellForRowAtIndexPath: или tableView:willDisplayCell:forRowAtIndexPath: или в любом другом методе, связанном с рисованием содержимого ваших ячеек. Если вы можете, попросите поставщика изображений (управление контентом?) предоставить изображения в размере, который отображает ваше табличное представление.

person Nick Toumpelis    schedule 26.11.2009