Переиспользование блоков на iOS
Переиспользование блоков в DivKit на iOS происходит при следующих событиях:
- Установка новой DivData.
- Cкроллинг элементов в сложных контейнерах:
gallery
,grid
,tabs
.
Переиспользование при установке новой DivData
DivKit всегда пытается переиспользовать уже созданные элементы. Для этого используется метод reuse
протокола UIViewRenderable
, который определяет, может ли блок быть переиспользован.
Диаграмма процесса переиспользования
Ниже представлена диаграмма процесса переиспользования блоков в iOS:
Процесс переиспользования включает следующие шаги:
- Проверка наличия view для переиспользования
- Проверка метода
isBestViewForReuse
для определения, является ли view лучшим кандидатом для переиспользования - Если view не является лучшим кандидатом, проверка метода
canConfigureBlockView
- Если view может быть переиспользован, обновление его конфигурации
- Если view не может быть переиспользован, создание нового view
- Конфигурация view и его возврат
Особенности реализации методов переиспользования
В процессе переиспользования блоков в DivKit используются два ключевых метода: canConfigureBlockView
и isBestViewForReuse
:
- canConfigureBlockView - базовый метод, который проверяет тип UIView. Его реализация обычно очень проста:
// Пример для ImageBlock
public func canConfigureBlockView(_ view: BlockView) -> Bool {
view is RemoteImageViewContainer
}
- isBestViewForReuse - для простых блоков (Image, Text) и некоторых составных блоков (Container, Gallery) по умолчанию просто вызывает
canConfigureBlockView
:
// Реализация по умолчанию в протоколе UIViewRenderable
public func isBestViewForReuse(_ view: BlockView) -> Bool {
canConfigureBlockView(view)
}
- isBestViewForReuse для некоторых сложных блоков - для определенных составных блоков (например, DecoratingBlock) имеет более сложную логику:
// Пример для DecoratingBlock
func isBestViewForReuse(_ view: BlockView) -> Bool {
guard let view = view as? DecoratingView,
view.childView != nil else { return false }
return child.isBestViewForReuse(view.childView!)
}
В этом примере isBestViewForReuse
не только проверяет тип view, но и:
- Требует наличия непустого дочернего view
- Рекурсивно проверяет, является ли дочерний view оптимальным для переиспользования
- Особенности составных блоков - блоки, содержащие коллекции дочерних элементов (Container, Gallery), делегируют переиспользование дочерних элементов специальному методу
reused
для массивов:
// В ContainerBlockView
blockViews = blockViews.reused(
with: model.children.map(\.content),
attachTo: self,
observer: observer,
overscrollDelegate: overscrollDelegate,
renderingDelegate: renderingDelegate
)
Метод reused
сам реализует двухуровневую систему переиспользования для каждого дочернего элемента.
Переиспользование в сложных контейнерах
В сложных контейнерах, таких как gallery
, grid
и tabs
, DivKit использует механизм переиспользования ячеек коллекций UIKit. Каждый блок имеет свойство reuseId
, которое используется для идентификации блоков, которые могут быть переиспользованы.
Например, в GalleryView
метод cellForItemAt
использует block.reuseId
для получения переиспользуемой ячейки из коллекции:
let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: block.reuseId,
for: indexPath
) as! CellType
По умолчанию reuseId
возвращает строку "DefaultReuseId", но блоки могут переопределить это свойство для более точного контроля над переиспользованием.
reuse_id
Использование свойства Для более эффективного переиспользования блоков в сложных контейнерах рекомендуется устанавливать свойство reuse_id
для блоков с одинаковой структурой. Это позволит DivKit более эффективно переиспользовать представления.
Пример:
{
"type": "gallery",
"items": [
{
"type": "container",
"reuse_id": "video_block",
"items": [
{
"type": "video",
...
}
]
},
{
"type": "container",
"reuse_id": "image_block",
"items": [
{
"type": "image",
...
}
]
},
{
"type": "container",
"reuse_id": "image_block",
"items": [
{
"type": "image",
...
}
]
},
{
"type": "container",
"reuse_id": "video_block",
"items": [
{
"type": "video",
...
}
]
}
]
}
В этом примере блоки с одинаковым reuse_id
будут переиспользоваться между собой. Это особенно важно для тяжелых объектов, таких как video
, чтобы избежать их ненужного пересоздания.
Узнать больше
Следите за новостями DivKit в Telegram-канале: http://t.me/divkit_news.
Также вы можете обсуждать интересующие вас темы в сообществе пользователей DivKit в Telegram: https://t.me/divkit_community_ru.