Неправильный тип поля поддержки Kotlin

Модель просмотра

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, аналогично тому, что указано в документации .

Трудно понять, что вы имеете в виду. Мы не знаем, что такое state, newsAdapter, _wordPressPostsState и другие. Кроме того, определение свойства для wordPressPostList вообще не является допустимым кодом Kotlin.

broot 02.07.2024 22:17

Что касается определения поля — извините, я не распознал новую функцию.

broot 02.07.2024 23:33

Какую версию Котлина вы используете? Я думал, что так называемая функция «явного резервного поля» все еще обсуждается.

Slaw 03.07.2024 04:34

Ах, неважно. Не знал прототип функции доступен начиная с Kotlin 1.7 с компилятором K2 (который стал компилятором по умолчанию в Kotlin 2.0).

Slaw 03.07.2024 04:42

@broot Я обновил вопрос, добавив теги Android, для тех, кто не очень знаком с шаблоном. state — типичный запечатанный класс, newsAdapter — ListAdapter Android, _wordPressPostsState — канал Kotlin.

Bitwise DEVS 03.07.2024 05:52
0
5
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ListAdapter требует новый экземпляр списка каждый раз, когда вы вызываете submitList(). Не имеет значения, является ли экземпляр списка изменяемым или нет, хотя вы, вероятно, не будете использовать с ним изменяемые списки именно потому, что каждый раз ему нужен новый экземпляр, и он сломается, если вы когда-нибудь измените список после его передачи в submitList().

toList() заставляет ваш код (вроде как) работать, потому что он создает новый экземпляр списка, а не потому, что он создает список, доступный только для чтения. Однако после того, как вы расширите то, что делаете, ваше поведение все равно будет нарушено, поскольку вы изменяете список после его отправки.

Без использования toList() вы каждый раз передаете ему один и тот же экземпляр списка, так что это не сработает. Когда вы передаете ListAdapter тот же экземпляр списка, который вы передали ранее, тогда, когда он пытается сравнить старый и новый списки, он видит, что они идентичны, поэтому не реагирует.

Кроме того, хотя в данном случае это не имеет значения, у вас есть недопонимание относительно апкастинга. Свойство с явным резервным полем преобразует значение поля в тип свойства. Итак, в этом случае MutableList преобразуется в список. Это не означает, что список больше не является изменяемым. Это все тот же экземпляр/ссылка MutableList. Повышение уровня означает, что код, который ссылается на него через свойство, не знает, что это MutableList, и не сможет напрямую его изменять, но он все равно остается MutableList.

На практике, я думаю, редко будет иметь смысл использовать свойство резервных полей с MutableList/List. Просто не принято передавать списки, доступные только для чтения, между классами, пока они все еще изменяются. Это хрупкий код. Гораздо чаще можно увидеть поддерживающие поля, используемые с MutableStateFlow и StateFlow или Flow. Мы всегда ожидаем, что потоки будут излучать значения и, следовательно, изменяться, даже если наша ссылка доступна только для чтения. И потоки предназначены для безопасного использования, в отличие от списков, которые ломаются, если их читать, пока другой поток записывает в них данные.

Tenfour04 03.07.2024 13:36

Спасибо большое, не заметил, что там просто апкастинг делается. Требование нового экземпляра списка для ListAdapter также является для меня новым.

Bitwise DEVS 03.07.2024 14:06

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