gpt4 book ai didi

android - 如何使用分页库在 Leanback VerticalGridSupportFragment 中实现分页?

转载 作者:行者123 更新时间:2023-12-03 13:25:36 25 4
gpt4 key购买 nike

我们正在尝试使用架构组件分页库在 Leanback VerticalGridSupportFragment 中实现分页。 Leanback 本身与分页库没有任何开箱即用的兼容性,因此我们扩展了它的 ObjectAdapter 类并设法很容易地实现附加和清除操作,但我们很难尝试使修改操作工作。在内容修改操作期间,分页库的 PagedList 类使用 AsyncPagedListDiffer 计算差异,该类在内部使用 PagedStorageDiffHelper 这是一个包私有(private)类,它在内部使用 PagedList 的包私有(private) PagedStorage 字段来访问实际的底层数据。因此,由于可见性限制,我们无法实现与分页库内部使用的相同逻辑。我们正在寻找一种干净而聪明的方法来使 Leanback 与 Paging 一起工作,而无需提取和修改两者的任何内部结构。这是我们的 ObjectAdapter 实现,它支持追加和清除数据,但不支持内容修改。

有没有人设法通过分页库在 Leanback 中实现分页?

class LeanbackVerticalGridPagedListAdapter<T>(
presenter: Presenter,
private val stubItem: T
) : ObjectAdapter(presenter) {

private val mUpdateCallback = object : ListUpdateCallback {

override fun onInserted(position: Int, count: Int) {
notifyItemRangeInserted(position, count)
}

override fun onRemoved(position: Int, count: Int) {
notifyItemRangeRemoved(position, count)
}

override fun onMoved(fromPosition: Int, toPosition: Int) {
notifyItemMoved(fromPosition, toPosition)
}

override fun onChanged(position: Int, count: Int, payload: Any?) {
notifyItemRangeChanged(position, count, payload)
}
}

private var mPagedList: PagedList<T>? = null
private var mSnapshot: PagedList<T>? = null

private val mPagedListCallback = object : PagedList.Callback() {
override fun onInserted(position: Int, count: Int) {
mUpdateCallback.onInserted(position, count)
}

override fun onRemoved(position: Int, count: Int) {
mUpdateCallback.onRemoved(position, count)
}

override fun onChanged(position: Int, count: Int) {
mUpdateCallback.onChanged(position, count, null)
}
}

override fun size(): Int =
mPagedList?.size
?: mSnapshot?.size
?: 0

override fun get(index: Int): T? =
mPagedList?.let {
it.loadAround(index)
it[index] ?: stubItem
} ?: mSnapshot?.let {
it[index]
} ?: throw IndexOutOfBoundsException("Item count is zero, getItem() call is invalid")

fun submitList(pagedList: PagedList<T>?) {
if (pagedList == null) {
val removedCount = size()
if (mPagedList != null) {
mPagedList!!.removeWeakCallback(mPagedListCallback)
mPagedList = null
} else if (mSnapshot != null) {
mSnapshot = null
}
// dispatch update callback after updating mPagedList/mSnapshot
mUpdateCallback.onRemoved(0, removedCount)
return
}

if (mPagedList == null && mSnapshot == null) {
// fast simple first insert
mPagedList = pagedList
pagedList.addWeakCallback(null, mPagedListCallback)

// dispatch update callback after updating mPagedList/mSnapshot
mUpdateCallback.onInserted(0, pagedList.size)
return
}

if (mPagedList != null) {
// first update scheduled on this list, so capture mPages as a snapshot, removing
// callbacks so we don't have resolve to updates against a moving target
mPagedList!!.removeWeakCallback(mPagedListCallback)
mSnapshot = mPagedList!!.snapshot() as PagedList<T>
mPagedList = null
}

if (mSnapshot == null || mPagedList != null) {
DevUtil.crashDuringDevelopment(IllegalStateException("must be in snapshot state to diff"))
}
}
}

最佳答案

如果有人还在寻找它,通过移植 PagedListAdapter 让它工作:

import androidx.leanback.widget.ArrayObjectAdapter
import androidx.leanback.widget.Presenter
import androidx.leanback.widget.PresenterSelector
import androidx.paging.AsyncPagedListDiffer
import androidx.paging.PagedList
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback

/**
* Base adapter class from leanback's ArrayObjectAdapter which supports paging
* @link androidx.paging.PagedListAdapter
* Use
* @link
* #submitList
* methods to submit PagedList returned by paging library
*/
@Suppress("unused")
class PagedArrayObjectAdapter<T> : ArrayObjectAdapter, ListUpdateCallback {

private val logTag = PagedArrayObjectAdapter::class.java.name
private val differ: AsyncPagedListDiffer<T>
private val listener: AsyncPagedListDiffer.PagedListListener<T> =
AsyncPagedListDiffer.PagedListListener { previousList, currentList ->
@Suppress("DEPRECATION")
onCurrentListChanged(currentList)
onCurrentListChanged(previousList, currentList)
}

constructor(diffCallback: DiffUtil.ItemCallback<T>) : this(
AsyncDifferConfig.Builder<T>(diffCallback).build()
)

constructor(config: AsyncDifferConfig<T>) : super() {
differ = AsyncPagedListDiffer(this, config)
differ.addPagedListListener(listener)
}

constructor(
presenter: Presenter,
diffCallback: DiffUtil.ItemCallback<T>
) : this(
presenter,
AsyncDifferConfig.Builder<T>(diffCallback).build()
)

constructor(
presenter: Presenter,
config: AsyncDifferConfig<T>
) : super(presenter) {
differ = AsyncPagedListDiffer(this, config)
differ.addPagedListListener(listener)
}

constructor(
presenterSelector: PresenterSelector,
diffCallback: DiffUtil.ItemCallback<T>
) : this(
presenterSelector,
AsyncDifferConfig.Builder<T>(diffCallback).build()
)

constructor(
presenterSelector: PresenterSelector,
config: AsyncDifferConfig<T>
) : super(
presenterSelector
) {
differ = AsyncPagedListDiffer(this, config)
differ.addPagedListListener(listener)
}

/**
* @link
* ListUpdateCallback#onInserted
*/
override fun onInserted(position: Int, count: Int) {
notifyItemRangeInserted(position, count)
}

/**
* @link
* ListUpdateCallback#onRemoved
*/
override fun onRemoved(position: Int, count: Int) {
notifyItemRangeRemoved(position, count)
}

/**
* @link
* ListUpdateCallback#onMoved
*/
override fun onMoved(fromPosition: Int, toPosition: Int) {
notifyItemMoved(fromPosition, toPosition)
}

/**
* @link
* ListUpdateCallback#onChanged
*/
override fun onChanged(position: Int, count: Int, payload: Any?) {
notifyItemRangeChanged(position, count, payload)
}

/**
* Set the new list to be displayed.
*
*
* If a list is already being displayed, a diff will be computed on a background thread, which
* will dispatch Adapter.notifyItem events on the main thread.
*
* @param pagedList The new list to be displayed.
*/
fun submitList(pagedList: PagedList<T>?) {
differ.submitList(pagedList)
}

/**
* Set the new list to be displayed.
*
*
* If a list is already being displayed, a diff will be computed on a background thread, which
* will dispatch Adapter.notifyItem events on the main thread.
*
*
* The commit callback can be used to know when the PagedList is committed, but note that it
* may not be executed. If PagedList B is submitted immediately after PagedList A, and is
* committed directly, the callback associated with PagedList A will not be run.
*
* @param pagedList The new list to be displayed.
* @param commitCallback Optional runnable that is executed when the PagedList is committed, if
* it is committed.
*/
fun submitList(pagedList: PagedList<T>?, commitCallback: Runnable?) {
differ.submitList(pagedList, commitCallback)
}


/**
* @link
* ArrayObjectAdapter#get
*/
override fun get(index: Int): T? {
return differ.getItem(index)
}

/**
* @link
* ArrayObjectAdapter#size
*/
override fun size(): Int {
return differ.itemCount
}

/**
* Returns the PagedList currently being displayed by the Adapter.
* <p>
* This is not necessarily the most recent list passed to
* @link
* #submitList(PagedList)
* because a diff is computed asynchronously between the new list and the current list before
* updating the currentList value. May be null if no PagedList is being presented.
*
* @return The list currently being displayed.
*
* @link
* #onCurrentListChanged(PagedList, PagedList)
*/
fun getCurrentList(): PagedList<T>? = differ.currentList

@Deprecated("")
fun onCurrentListChanged(currentList: PagedList<T>?) {
}

@Suppress("MemberVisibilityCanBePrivate", "UNUSED_PARAMETER")
fun onCurrentListChanged(previousList: PagedList<T>?, currentList: PagedList<T>?) {
}
}

关于android - 如何使用分页库在 Leanback VerticalGridSupportFragment 中实现分页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56054947/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com