Android 存储库模式 - 如何从视图模型更新嵌套的回收器视图项
Android Repository pattern - how to update a nested recycler view item from view model
我正在使用 ViewModel 和存储库模式来获取列表中的数据。这些项目排列为行和产品的列表。行 class 中有产品。产品可以水平滚动。我正在使用嵌套在另一个回收器视图(垂直方向)中的线性布局管理器(水平方向)的回收器视图。通过 ViewModel 获取项目并在回收器视图中呈现非常简单。挑战在于,当我将商品添加到购物车时尝试更新商品(它们的数量)。单击按钮(加号)时,回调将通过侦听器发送到视图模型。水平适配器将请求发送回容器(垂直)适配器,垂直适配器将请求发送回视图模型。
// The horizontal adapter
class SimpleProductAdapter(
private val shopId: String,
private val listener: (product: CartProduct) -> Unit
) :
ListAdapter<CartProduct, RecyclerView.ViewHolder>(...DiffCallbackGoesHere) {
// ... some more things here
fun bind(item: CartProduct?) {
view.add_to_cart_button.setOnClickListener {
listener(item)
}
}
垂直适配器结构相似
class RowAdapter(
private val shopId: String,
private val listener: (product: CartProduct) -> Unit
) :
PagedListAdapter<Row, RecyclerView.ViewHolder>(...RowDiffCallbackGoesHere) {
// ... some more things here
fun bind(item: Row?) {
SimpleProductAdapter(shopId) { product ->
listener(product)
}
}
片段中存在视图模型调用的主要站点:
val rowAdapter = RowAdapter(args.shopId) { product->
if (actionType == ADD_TO_CART_ACTION) viewModel.buy(product)
.observe(viewLifecycleOwner, Observer {
view.swipe.isRefreshing = it is Resource.Loading
// I want to update the quantity here on success result
if(Resource is Success) {}
})
当结果为Success时,我想更新数量;这里有两件事具有挑战性
- 我正在使用分页库中的 PagedListAdapter,它为我提供了一个(假设)不可变的产品列表。
- 即使我更新了 PagedList 并发出了 notifyDataSetChanged,仅仅更改大量项目的单个计数也太过分了。
我希望找到一种方法,让我可以轻松地针对特定产品进行更新,或者我一直在网上看到的另一种选择是 构建自定义布局管理器 所以我可以有一个单一的适配器,在一次传递中绘制所有内容,而无需嵌套回收器视图。这样更新项目会变得更容易(找不到关于此的代码示例)。
有什么建议吗
在 Paging3 中,有计划最终添加一个 API 来支持粒度更新而不失效:https://issuetracker.google.com/160232968
目前,您必须使数据失效才能更新后备数据集。不过,一般来说,DiffUtil 可以很好地向用户隐藏这一点。
我正在使用 ViewModel 和存储库模式来获取列表中的数据。这些项目排列为行和产品的列表。行 class 中有产品。产品可以水平滚动。我正在使用嵌套在另一个回收器视图(垂直方向)中的线性布局管理器(水平方向)的回收器视图。通过 ViewModel 获取项目并在回收器视图中呈现非常简单。挑战在于,当我将商品添加到购物车时尝试更新商品(它们的数量)。单击按钮(加号)时,回调将通过侦听器发送到视图模型。水平适配器将请求发送回容器(垂直)适配器,垂直适配器将请求发送回视图模型。
// The horizontal adapter
class SimpleProductAdapter(
private val shopId: String,
private val listener: (product: CartProduct) -> Unit
) :
ListAdapter<CartProduct, RecyclerView.ViewHolder>(...DiffCallbackGoesHere) {
// ... some more things here
fun bind(item: CartProduct?) {
view.add_to_cart_button.setOnClickListener {
listener(item)
}
}
垂直适配器结构相似
class RowAdapter(
private val shopId: String,
private val listener: (product: CartProduct) -> Unit
) :
PagedListAdapter<Row, RecyclerView.ViewHolder>(...RowDiffCallbackGoesHere) {
// ... some more things here
fun bind(item: Row?) {
SimpleProductAdapter(shopId) { product ->
listener(product)
}
}
片段中存在视图模型调用的主要站点:
val rowAdapter = RowAdapter(args.shopId) { product->
if (actionType == ADD_TO_CART_ACTION) viewModel.buy(product)
.observe(viewLifecycleOwner, Observer {
view.swipe.isRefreshing = it is Resource.Loading
// I want to update the quantity here on success result
if(Resource is Success) {}
})
当结果为Success时,我想更新数量;这里有两件事具有挑战性
- 我正在使用分页库中的 PagedListAdapter,它为我提供了一个(假设)不可变的产品列表。
- 即使我更新了 PagedList 并发出了 notifyDataSetChanged,仅仅更改大量项目的单个计数也太过分了。
我希望找到一种方法,让我可以轻松地针对特定产品进行更新,或者我一直在网上看到的另一种选择是 构建自定义布局管理器 所以我可以有一个单一的适配器,在一次传递中绘制所有内容,而无需嵌套回收器视图。这样更新项目会变得更容易(找不到关于此的代码示例)。
有什么建议吗
在 Paging3 中,有计划最终添加一个 API 来支持粒度更新而不失效:https://issuetracker.google.com/160232968
目前,您必须使数据失效才能更新后备数据集。不过,一般来说,DiffUtil 可以很好地向用户隐藏这一点。