Модель просмотра
private val _wordPressPostsState = Channel<WordPressPostsState>()
val wordPressPostList: List<WordPressPostDataDomain>
field = mutableListOf<WordPressPostDataDomain>()
Внутри функции, вызывающей вариант использования, который возвращает поток
when (it) {
is RequestStatus.Success -> {
if (it.data.postList.isNotEmpty()) {
wordPressPostList.addAll(it.data.postList)
}
_wordPressPostsState.send(WordPressPostsState.FetchSuccess(wordPressPostList.toList()))
}
}
Фрагмент
val newsAdapter: ListAdapter
newsAdapter.submitList(state.postList)
ListAdapter не будет работать без вызова .toList()
ни в state.postList
, ни в wordPressPostList
при передаче его в состояние WordPressPostsState.FetchSuccess
во ViewModel. Это означает, что wordPressPostList
по-прежнему является MutableList
.
Одна вещь, которую я заметил, это то, что тип данных был показан как List внутри и снаружи, но на самом деле он ведет себя как изменяемый в ViewModel и неизменяемый во Fragment, аналогично тому, что указано в документации .
Что касается определения поля — извините, я не распознал новую функцию.
Какую версию Котлина вы используете? Я думал, что так называемая функция «явного резервного поля» все еще обсуждается.
Ах, неважно. Не знал прототип функции доступен начиная с Kotlin 1.7 с компилятором K2 (который стал компилятором по умолчанию в Kotlin 2.0).
@broot Я обновил вопрос, добавив теги Android, для тех, кто не очень знаком с шаблоном. state
— типичный запечатанный класс, newsAdapter
— ListAdapter Android, _wordPressPostsState
— канал Kotlin.
ListAdapter требует новый экземпляр списка каждый раз, когда вы вызываете submitList()
. Не имеет значения, является ли экземпляр списка изменяемым или нет, хотя вы, вероятно, не будете использовать с ним изменяемые списки именно потому, что каждый раз ему нужен новый экземпляр, и он сломается, если вы когда-нибудь измените список после его передачи в submitList()
.
toList()
заставляет ваш код (вроде как) работать, потому что он создает новый экземпляр списка, а не потому, что он создает список, доступный только для чтения. Однако после того, как вы расширите то, что делаете, ваше поведение все равно будет нарушено, поскольку вы изменяете список после его отправки.
Без использования toList()
вы каждый раз передаете ему один и тот же экземпляр списка, так что это не сработает. Когда вы передаете ListAdapter тот же экземпляр списка, который вы передали ранее, тогда, когда он пытается сравнить старый и новый списки, он видит, что они идентичны, поэтому не реагирует.
Кроме того, хотя в данном случае это не имеет значения, у вас есть недопонимание относительно апкастинга. Свойство с явным резервным полем преобразует значение поля в тип свойства. Итак, в этом случае MutableList преобразуется в список. Это не означает, что список больше не является изменяемым. Это все тот же экземпляр/ссылка MutableList. Повышение уровня означает, что код, который ссылается на него через свойство, не знает, что это MutableList, и не сможет напрямую его изменять, но он все равно остается MutableList.
На практике, я думаю, редко будет иметь смысл использовать свойство резервных полей с MutableList/List. Просто не принято передавать списки, доступные только для чтения, между классами, пока они все еще изменяются. Это хрупкий код. Гораздо чаще можно увидеть поддерживающие поля, используемые с MutableStateFlow и StateFlow или Flow. Мы всегда ожидаем, что потоки будут излучать значения и, следовательно, изменяться, даже если наша ссылка доступна только для чтения. И потоки предназначены для безопасного использования, в отличие от списков, которые ломаются, если их читать, пока другой поток записывает в них данные.
Спасибо большое, не заметил, что там просто апкастинг делается. Требование нового экземпляра списка для ListAdapter также является для меня новым.
Трудно понять, что вы имеете в виду. Мы не знаем, что такое
state
,newsAdapter
,_wordPressPostsState
и другие. Кроме того, определение свойства дляwordPressPostList
вообще не является допустимым кодом Kotlin.