在使用Room的Android应用中,PagedList正在增长,但从未萎缩

时间:2018-10-06 06:53:27

标签: java android kotlin

在我的Android应用中,我有一个非常基本的RecyclerView实现,该实现通过使用RoomPaging library来显示数据库中的条目。

从数据库中获取条目的Dao方法:

@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}")
    }
})

此后,我将5000个条目插入数据库,相应的日志条目如下:

  

D / _tag:位置: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回答)

编辑

整个适配器的代码:

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的{​​{1}}的布局:

RecyclerView

1 个答案:

答案 0 :(得分:1)

Android Architecture Components团队的Chris Craik刚刚在Reddit上确认,到目前为止,Paging库尚未删除分页数据(但即将到来):

  

它已合并(12),但是由于被合并,我们尚未发布它   在AndroidX切换过程中要格外小心。拱门要小心   以避免在AndroidX迁移过程中引起回归(因为那些   迁移非常复杂)。

     

现在AndroidX稳定了,我们可以发布了,因此我们将了解   即将推出。