Android后倾:如何更新RowsSupportFragment中的嵌套行项

fbcarpbf  于 2023-01-24  发布在  Android
关注(0)|答案(1)|浏览(195)

"嘿伙计们"
我正在使用*leanback*库开发androidTV应用程序。
我应该显示类别列表,每个类别都有自己的内容列表。对于这种方法,leanback提供了
RowsSupportFragment
,您可以在其中显示这种类型的UI。

这里我使用房间+ LiveData + Retrofit + Glide来执行和实现屏幕,但问题是,API不会直接传递内容封面图像,所以开发人员应该下载每个内容封面图像,存储它,然后显示隐藏的内容。
每件事都在工作,但在第一次,如果没有封面图片的内容,我会下载封面并存储它,但内容将不会被触发以获取和显示图像。使用notifyItemRangeChanged和类似的方法将 Flink 和重置列表行,所以这不是一个好的解决方案。
这是我正在使用的diffUtils,一个用于类别列表,一个用于每个内容列表。

private val diffCallback = object : DiffCallback<CardListRow>() {
    override fun areItemsTheSame(oldItem: CardListRow, newItem: CardListRow): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItem: CardListRow, newItem: CardListRow): Boolean {
        return oldItem.cardRow.contents?.size == newItem.cardRow.contents?.size
    }
}

private val contentDiffCallback = object : DiffCallback<ContentModel>() {
    override fun areItemsTheSame(oldItem: ContentModel, newItem: ContentModel): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItem: ContentModel, newItem: ContentModel): Boolean {
        return oldItem.hashCode() == newItem.hashCode()
    }

}

如前所述,存储使用room,检索数据为LiveData,并在我的片段中观察它们,等等。我还没有发布所有代码进行总结。
如果你有任何想法或类似的源代码,我将不胜感激.谢谢

编辑:12月2日星期五---添加更多详细信息

这是我的实时数据观察器,持有和观察类别和数据的主要列表

private fun initViewModel() {
    
            categoriesViewModel.getCategoriesWithContent().observe(viewLifecycleOwner) { result ->
                val categoryModelList = MergedContentMapper().toCategoryModelList(result)
                initData(categoryModelList)
            }
    }

这是使用ArrayObjectAdapter创建行的场景

private fun initData(categoryModelList: List<CategoryModel>) {
    showLoading(false)
    createRows(categoryModelList)
}

private fun createRows(categoryModelList: List<CategoryModel>) {
    val rowItemsList: MutableList<CardListRow> = arrayListOf()
    // create adapter for the whole fragment. It displays Rows.
    categoryModelList.forEach { categoryModel ->
        // create adapter for each row that can display CardView using CardPresenter
        val cardListRow = createCardRow(categoryModel)
        // add card list rows into list
        rowItemsList.add(cardListRow)
    }

    // set item with diff util
    rowsAdapter.setItems(rowItemsList, diffCallback)

}

private fun createCardRow(categoryModel: CategoryModel): CardListRow {
    val contentList = categoryModel.contents ?: emptyList()
    val cardListRowsAdapter = ArrayObjectAdapter(CardPresenterSelector(context, this))
    cardListRowsAdapter.setItems(contentList, contentDiffCallback)
    val headerItem = HeaderItem(categoryModel.title)
    return CardListRow(headerItem, cardListRowsAdapter, categoryModel)
}
y53ybaqx

y53ybaqx1#

您的代码看起来是正确的,但它缺少了告诉Presenter您的项目发生了什么变化的部分,这样它就可以只更改那部分数据,而不需要重新绑定整个内容以避免 Flink 。
当你的DiffCallback检测到项目是相同的,但是内容已经改变,它将调用它的getChangePayload()函数来收集关于改变的细节,并将它们传递给Presenter
首先,您需要将DiffCallback.getChangePayload()函数重写为如下内容:

override fun getChangePayload(oldItem: ListRow, newItem: ListRow): Any {
    return when {
        oldItem.headerItem.name != newItem.headerItem.name -> "change_title"
        else -> "change_items"
    }
}

这样,您的ListRowPresenter将收到ListRowPresenter.onBindViewHolder()重载中发生了什么变化的信息,该重载接收有效负载列表(由您的DiffCallback返回),如下所示:

override fun onBindViewHolder(
        viewHolder: Presenter.ViewHolder?,
        item: Any?,
        payloads: MutableList<Any>?
    ) {
    when {
        payloads == null || payloads.isEmpty() -> {
            // Your DiffCallback did not returned any information about what changed.
            super.onBindViewHolder(viewHolder, item, payloads)
        }
        "change_title" in payloads -> getRowViewHolder(viewHolder)?.let {
            headerPresenter.onBindViewHolder(it.headerViewHolder, item)
        }
        "change_items" in payloads -> {
            val newItems = ((item as? ListRow)?.adapter as? ArrayObjectAdapter)?.unmodifiableList<Item>()
            when (val listRowAdapter = (getRowViewHolder(viewHolder).row as? ListRow)?.adapter) {
                is ArrayObjectAdapter -> listRowAdapter.setItems(newItems, null)
                else -> super.onBindViewHolder(viewHolder, item, payloads)
            }
        }
        else -> {
            // If you don't know what changed just delegate to the super.
            super.onBindViewHolder(viewHolder, item, payloads)
        }
    }
}

根据需要自定义DiffCallback.getChangePayload()的实现。您可以返回此函数中的更改列表,并在ListRowPresenter.onBindViewHolder()中处理所有更改。
我最近写了一个blog post,其中的示例可能会有所帮助。

相关问题