PagedList растет, но никогда не сокращается в Android-приложении с помощью Room - PullRequest
0 голосов
/ 06 октября 2018

В моем приложении для Android есть базовая реализация RecyclerView, которая показывает записи из базы данных, используя Комната с библиотекой Paging .

Метод Даокоторый выбирает записи из базы данных:

@Query("SELECT * FROM entries")
abstract fun findAll(): DataSource.Factory<Int, Entry>

И вот как LiveData построен из возвращенного DataSource.Factory в моем ViewModel:

private val config = PagedList.Config.Builder()
        .setEnablePlaceholders(false)
        .setInitialLoadSizeHint(512)
        .setPrefetchDistance(256)
        .setPageSize(256)
        .build()

val entries = LivePagedListBuilder(entryService.findAll(), config).build()
// (entryService here just calls through to the Dao)

Я просто наблюдаю заэто LiveData и передать обновленный PagedList моему RecyclerView.Adapter.

Соответствующему фрагменту RecyclerView.Adapter:

private val differ = AsyncPagedListDiffer<Entry>(this, DIFF_CALLBACK)

fun submitList(list: PagedList<Entry>) {
    differ.submitList(list)
}

(я не использую PagedListAdapter, потому что яМне понадобится более детальный контроль в моем адаптере позже)

Кажется, все работает нормально, но когда я начал отслеживать использование памяти приложением, я начал подозревать, что элементы PagedList не обрабатываются должным образом.

Я добавил следующее Callback в submitList():

list.addWeakCallback(differ.currentList?.snapshot(), object : PagedList.Callback() {
    override fun onChanged(position: Int, count: Int) {
        Log.d("_tag", "Position: $position | Changed: $count" +
                " | Size: ${list.size}")
    }

    override fun onInserted(position: Int, count: Int) {
        Log.d("_tag", "Position: $position | Inserted: $count" +
                " | Size: ${list.size}")
    }

    override fun onRemoved(position: Int, count: Int) {
        Log.d("_tag", "Position: $position | Removed: $count" +
                " | Size: ${list.size}")
    }
})

После этого я вставил 5 000 записей в базу данных, и соответствующая запись в журнале была следующей:

D / _tag: Position: 0 |Вставлено: 512 |Размер: 512

Это нормально, это ожидаемый результат.

Но когда я начинаю прокручивать список вниз, записи журнала выглядят следующим образом:

D / _tag: Позиция: 512 |Вставлено: 256 |Размер: 768

D / _tag: Позиция: 768 |Вставлено: 256 |Размер: 1024

D / _tag: Позиция: 1024 |Вставлено: 256 |Размер: 1280

D / _tag: Позиция: 1280 |Вставлено: 256 |Размер: 1536

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

Мои вопросы относительно этого поведения:

  • Почему onRemoved() никогда не вызывается?

    Является ли PagedList постоянно растущим списком, а предметы остаются в памяти?

    Разве смысл пейджинга не в том, чтобы загружать новые записи по запросу и удалять также старых (не видимых)?

  • Почемуостанавливаются ли журналы после 1536-й записи, даже если я прокручиваю путь мимо этой записи?

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

Я был бы очень признателен, если бы кто-то мог объяснить мне поведение.

(также приветствуются ответы на Java)

EDIT :

Код всего адаптера:

class EntryListAdapter
        : RecyclerView.Adapter<EntryListAdapter.EntryViewHolder>() {

    private val differ = AsyncPagedListDiffer<Entry>(this, DIFF_CALLBACK)

    fun submitList(list: PagedList<Entry>) {
        differ.submitList(list)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
            EntryViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val entryItemView = inflater.inflate(R.layout.item_entry, parent, false)

        return EntryViewHolder(entryItemView)
    }

    override fun onBindViewHolder(holder: EntryViewHolder, position: Int) {
        differ.getItem(position)?.let { holder.bindTo(it) }
    }

    override fun getItemId(position: Int): Long {
        return differ.getItem(position)?.id ?: RecyclerView.NO_ID
    }

    override fun getItemCount(): Int {
        return differ.currentList?.size ?: 0
    }

    inner class EntryViewHolder(itemView: View) :
            RecyclerView.ViewHolder(itemView) {

        fun bindTo(entry: Entry) {
            itemView.textEntryTitle.text = entry.title
        }
    }

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Entry>() {
            override fun areItemsTheSame(entry1: Entry, entry2: Entry): Boolean {
                return entry1.id == entry2.id
            }

            override fun areContentsTheSame(entry1: Entry, entry2: Entry): Boolean
            {
                return entry1 == entry2
            }
        }
    }
}

EDIT2 :

Макет Fragment, в котором размещается RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/mainRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

1 Ответ

0 голосов
/ 07 октября 2018

Крис Крейк из команды Android Architecture Components только что подтвердил на Reddit , что на данный момент библиотека подкачки не отбрасывает постраничные данные (но это происходит):

Этообъединен ( 1 и 2 ), но мы еще не выпустили его из-за особой осторожности при переключении AndroidX.Arch должен был быть осторожен, чтобы не вызывать регрессии во время миграции на AndroidX (так как эти миграции достаточно сложны).

Теперь, когда AndroidX стабилен, мы можем выпустить релиз, так что скоро мы увидим, как его выпустить..

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