Отслеживание показов предметов в Android ListView

У меня есть ListView и ArrayAdapter в качестве его адаптера. Я хотел бы отслеживать количество показов каждого элемента CustomListViewItem.

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

Что я попробовал:

Одна вещь, которую я попытался, состояла в том, чтобы установить OnOScrollListener для представления списка и сделать отслеживание в обратном вызове onScroll(AbsListView, int firstVisibleItem, int visibleItemCount, int totalItemCount).

Я могу использовать firstVisibleItem и visibleItemCount, чтобы сделать работу. В документации говорится, что это вызывается после завершения прокрутки. Но, кажется, его часто вызывают, когда прокрутка медленная. Вероятно, после каждого пикселя прокрутки. Это делает свиток очень медленным.

Есть ли другой способ сделать это? Используя какой-то обратный вызов, который вызывается для каждого элемента, когда он выходит из поля зрения или становится видимым?

Я много искал в Интернете и не видел ни одной записи, связанной с таким типом отслеживания.

2 ответа

Решение

Я не мог найти другой способ сделать это. Итак, я оптимизировал то, что я уже делал. Я думал, что должен поделиться этим, поскольку это может помочь кому-то еще.

Я использую firstVisibleItem и visibleItemCount только для обратного вызова onScroll(). Я использую две переменные для хранения информации о предыдущем обратном вызове onScroll(). Они есть:

prevVisibleStart и prevVisibleEnd

Давайте рассмотрим пример, чтобы понять алгоритм. Предположим сначала, что после первого onScroll()

firstVisibleItem = 0 иvisibleItemCount = 3 => lastVisibleItem = 2

Они используются для установки моих предыдущих видимых состояний.

Итак, prevVisibleStart = firstVisibleItem = 3 и prevVisibleEnd = firstVisibleItem + visibleItemCount - 1 = 2

Теперь, если я прокручиваю вниз, у меня всегда будет

firstVisibleItem > = prevVisibleStart и lastVisibleItem > = prevVisibleEnd

Таким образом, если предыдущий диапазон был от 0 до 2. Новый диапазон был бы примерно как от 1 до 3. Так как я уже рассмотрел от 0 до 2 для показа. Я буду рассматривать только 3 как новое впечатление. Причина в том, что представления 1, 2 все еще находятся в поле зрения, и они не исчезли из поля зрения. Таким образом, новое впечатление не учитывается. Это эффективно дает правильный диапазон для просмотра показов, а также уменьшает диапазон для проверки.

Точно так же это можно сделать для прокрутки вверх. Предположим, что текущие видимые элементы 2-4. Теперь после прокрутки вверх диапазон становится (скажем)1-3. Это означает, что 1 вошел в поле зрения. Итак, посчитайте впечатление для этого взгляда. Таким образом, количество операций в onScroll() значительно сокращается.

Пример кода следует

Диапазон [ij) считается для впечатления.

private static int prevVisibleStart=-1;
private static int prevVisibleEnd=-1;
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
 if(prevVisibleStart <= firstVisibleItem) {
  // scroll down
  i = Math.max(firstVisibleItem, prevVisibleEnd + 1);
  j = firstVisibleItem + visibleItemCount;
 } else {
  // scroll up
  i = firstVisibleItem;
  j = Math.min(prevVisibleStart, firstVisibleItem + visibleItemCount);
 }
 prevVisibleStart = firstVisibleItem;
 prevVisibleEnd = firstVisibleItem + visibleItemCount - 1;
 // now can use [i-j) to update impressions
}

Определите обратный вызов в своем адаптере

      var onAttachView: ((position: Int) -> Unit)? = null

и вызовите его в методе адаптера onViewAttachedToWindow

       override fun onViewAttachedToWindow(holder: ViewHolder) {
    super.onViewAttachedToWindow(holder)
    onAttachView?.invoke(holder.bindingAdapterPosition)
}

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

Другие вопросы по тегам