Closed sadr0b0t closed 2 years ago
https://github.com/sadr0b0t/yashlang/commit/053ff9d6a1f846ab1bb98d4ac9ceb58bc5f19140 https://github.com/sadr0b0t/yashlang/commit/9247a067bbfafdc169ca7f0ff712a6581e94588b
Фикс.
Основная причина истории - реализация DIFF_CALLBACK areContentsTheSame, которая должна выглядеть примерно вот так:
@Override
public boolean areContentsTheSame(VideoItem oldItem, VideoItem newItem) {
// вставим небольшой хак, чтобы не моргала иконка обновленного элемента -
// перекинем кэш загруженной иконки со старого элемента на новый элемент,
// раз уж он к нам сюда пришел
newItem.setThumbBitmap(oldItem.getThumbBitmap());
// Здесь следует перечислить все поля, которые в том или ином виде
// отображены на элементе списка: например, прогресс (pausedAt), или
// статус "любомое" (starred). В таком случае при изменении этих полей
// (например, при сохранении новой позиции или переключении состояния
// звездочки) будет автоматически изменяться состояние элемента в загруженном
// списке (на текущем экране - например, в рекомендациях на экране плеера,
// или в списке на экране, из которого был открыт плеер)
// Но внесем сюда только изменяемые позиции (имя или адрес ролика не изменяются,
// поэтому сравнивать дополнительно их нет большого смысла)
return (oldItem.isStarred() == newItem.isStarred() &&
oldItem.getPausedAt() == newItem.getPausedAt() &&
oldItem.isHasOffline() == newItem.isHasOffline() &&
oldItem.isBlacklisted() == newItem.isBlacklisted() &&
oldItem.isEnabled() == newItem.isEnabled() &&
oldItem.getViewCount() == newItem.getViewCount() &&
( (oldItem.getLastViewedDate() != null && newItem.getLastViewedDate() != null &&
oldItem.getLastViewedDate().equals(newItem.getLastViewedDate())) ||
(oldItem.getLastViewedDate() == null && newItem.getLastViewedDate() == null) ) &&
( (oldItem.getStarredDate() != null && newItem.getStarredDate() != null &&
oldItem.getStarredDate().equals(newItem.getStarredDate())) ||
(oldItem.getStarredDate() == null && newItem.getStarredDate() == null) ) );
}
Иначе события из базы данных ловятся, но метод onBindViewHolder не вызывается (раньше похоже, действительно, все эти проблемы скрывал notifyDataSetChanged).
В SearchVideoActivtiy дополнительно еще обрубал videoItemsLiveData.removeObservers(this) в onPause, поэтому он просто переставал получать любые события после переключения экрана.
На самом деле, вручную управлять videoItemsLiveData не нужно - он сам всё в нужный момент сделает. https://stackoverflow.com/questions/63737845/when-should-i-remove-livedata-observer-on-android#63738811 https://developer.android.com/topic/libraries/architecture/livedata#the_advantages_of_using_livedata
Дополнительный бонус изменений - элементы в списке рекомендаций теперь изменяются автоматом при любых обновлениях соответствующих роликов (например, если в рекомендациях видно текущий ролик, внизу в этом списке появится звездочка, если установить звездочку на ролики, или обновится прогресс, если переместить ползунок проигрыания, или появится иконка "дискетка" после того, как у ролика докачается кэш потока в фоне; или если заблокировать текущий ролик, он сам улетит и из рекомендаций).
Но только не для случайных рекомендаций при обычном открытии ролика, т.к. там используется VideoItemArrayAdapter, а не VideoItemPagedListAdapter. Следует реализовать эти измения для ArrayAdapter в ручном режиме или использовать PagedListAdapter вместо ArrayAdapter (так просто это не сделать; в любом случае - в другом тикете).
Еще заметил: если в рекомендациях в режиме "любимое" убрать звезду с ролика, он исчезнет из рекомендаций, а если поставить обратно (не переключая ролик), то он обратно не появится
Например: в настройках список плейлистов (плейлисты отмечены переключателями вкл/выкл) > кликнуть на плейлист (перейти в настройки конкретного плейлиста), выключить плейлист (или включить) на этом экране > вернуться в список плейлистов > переключатель в списке не получит актуальное значение.
Аналогично: состояние "звездочка" для роликов видео - если открыть ролик из экрана "Поиск" или из экрана "Плейлист" - не обновляется в списке, если вернуться в него из экрана плеера, на котором флаг "звездочка" можно поменять. Но: состояние обновиться в списке "История" или "Любимое" (в любомом выключенный ролик просто изсчезнет из списка).
Скорее всего отвалилось после этой оптимизации: https://github.com/sadr0b0t/yashlang/issues/129 , т.к. раньше все списком обновлялись целиком на любой чих, а сейчас изменения идут точечно, т.е. какое-то событие на обновление могли и пропустить.