Как использовать библиотеку подкачки AAC с размером списка, отличным от размера списка, возвращаемого базой данных Room - PullRequest
0 голосов
/ 19 сентября 2018

Я пытаюсь использовать новые Paging Library и Room в качестве базы данных, но я столкнулся с проблемой, возвращаемый базой данных PagedList не должен быть тем же списком, отправленным в пользовательский интерфейс.map некоторые объекты, прежде чем показывать их пользователю, и во время этой операции map я изменяю размер списка (добавление элементов), очевидно, Paging Library не поддерживает этот тип операции, потому что при попытке запустить приложение яполучить это исключение:

Caused by: java.lang.IllegalStateException: Invalid Function 'function_name' changed return size. This is not supported.

Глядя на исходный код библиотеки подкачки, вы видите этот метод:

static <A, B> List<B> convert(Function<List<A>, List<B>> function, List<A> source) {
    List<B> dest = function.apply(source);
    if (dest.size() != source.size()) {
        throw new IllegalStateException("Invalid Function " + function
            + " changed return size. This is not supported.");
    }
    return dest;
}

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

Это то, что я делаю

DAO

@Query("SELECT * FROM table_name")
fun getItems(): DataSource.Factory<Int, Item>

LocalSource

fun getItems(): DataSource.Factory<Int, Item> {
    return database.dao().getItems()
        .mapByPage { map(it) } // This map operation changes the list size
}

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Я думаю, что нашел решение ..

Хотя это обходной путь, он работал для меня.

В моем случае я пытался создать алфавитный секционированный список для именкак это:

**A - HeaderItem**
Aaron - Item
Anny - Item
**B - HeaderItem**
Bob - Item
Bil
**C - HeaderItem**
....

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

То, что я сделал, объект HeaderItem оборачивает элемент следующим образом:

Сначала все элементы реализуют интерфейс ListItem

interface ListItem{
 const val HEADER = 0
 const val ITEM = 1
 fun getItemType() : Int
}

Затем элементы заголовка выглядят какthis

class HeaderItem(val headerTitle : String, val item : Item) : ListItem {
  @override
  fun getItemType() : Int {
    return ListItem.HEADER
  }
}

Затем, когда я сопоставляю элементы, при добавлении HeaderItem он принимает Item, таким образом, размер отображаемого PagedList не изменяется.Сейчас я не получаю это исключение.

Однако, это создает некоторую дополнительную работу, так как мне пришлось явно установить оформление HeaderItem, а также в адаптере, при привязке элемента заголовка мне пришлось позаботиться о внутреннем Item + всей его логике, такой как прослушиватели щелчков и т. Д.'.

Буду рад, если будет поддержка изменений размера списка из коробки.

0 голосов
/ 24 сентября 2018

Я сталкиваюсь с той же проблемой и все еще ищу лучшее решение.
В моем случае мне нужно отобразить 1 секцию , прежде чем каждый пользователей загрузит из API, и вот мой обходной путь,

class UsersViewModel : ViewModel() {
    var items: LiveData<PagedList<RecyclerItem>>

    init {
        ...
        items = LivePagedListBuilder<Long, RecyclerItem>(
            sourceFactory.mapByPage { it -> mapUsersToRecyclerItem(it) }, config).build()
    }

    private fun mapUsersToRecyclerItem(users: MutableList<User>): List<RecyclerItem> {
        val numberOfSection = 1
        for (i in 0 until numberOfSection) {
            users.add(0, User()) // workaround, add empty user here
        }

        val newList = arrayListOf<RecyclerItem>()
        newList.add(SectionItem())
        for (i in numberOfSection until users.size) {
            val user = users[i]
            newList.add(UserItem(user.login, user.avatarUrl))
        }
        return newList
    }
}

Мой текущий пользовательский класс

data class User(
    @SerializedName("login")
    val login: String,
    @SerializedName("id")
    val id: Long = 0,
    @SerializedName("avatar_url")
    val avatarUrl: String
) {
    constructor() : this("", 0, "")
}

Конечно, для отображения Section у меня будет другой способ без добавления его к RecyclerView data list (например, использование только позиции), нов моем случае пользователь может удалить элемент из списка, поэтому использование позиции может затруднить обработку

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...