gpt4 book ai didi

android - 如何更新 RecyclerView 项目内的绑定(bind)?

转载 作者:行者123 更新时间:2023-12-04 12:41:56 30 4
gpt4 key购买 nike

想象一个 StackOverflow 问题列表,这些问题可以单独被赞成和反对。他们每个人都有一个显示其投票数的计数。点击 upvote 增加一,点击 downvote 减少一。这就是我想要实现的总体思路。布局,rv_item.xml (为简洁起见)对于 RecyclerView 中的单个项目:

data>
<variable
name="item"
type="com.mycodez.Item"/>

<variable
name="vm"
type="com.mycodez.ListViewModel" />
</data>

<Button
android:id="@+id/decrease_quantity"
android:onClick="@{() -> vm.decrementItemQuantity(item)}"/>

<TextView
android:id="@+id/quantity"
android:text="@{String.valueOf(item.quantity)}"
tools:text="1" />

<Button
android:id="@+id/increase_quantity"
android:onClick="@{() -> vm.incrementItemQuantity(item)}"/>

在哪里 @+id/decrease_quantity类似于投反对票, @+id/quantity类似于计票, @+id/increase_quantity类似于赞成票。适配器:
class ListRvAdapter extends RecyclerView.Adapter<ListRvAdapter.ViewHolder> {
private List<Item> items;
private ListViewModel viewModel;
private LifecycleOwner lifecycleOwner;

ListRvAdapter(List<Item> items, ListViewModel viewModel, LifecycleOwner lifecycleOwner) {
this.items = items;
this.viewModel = viewModel;
this.lifecycleOwner = lifecycleOwner;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
RvItemBinding binding = RvItemBinding.inflate(layoutInflater, parent, false);
return new ViewHolder(binding, viewModel, lifecycleOwner);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.bind(items.get(position));
}

@Override
public int getItemCount() {
return items.size();
}

public static class ViewHolder extends RecyclerView.ViewHolder {
private final RvItemBinding binding;
private ListViewModel viewModel;
private LifecycleOwner lifecycleOwner;

ViewHolder(RvItemBinding binding, ListViewModel viewModel, LifecycleOwner lifecycleOwner) {
super(binding.getRoot());
this.binding = binding;
this.viewModel = viewModel;
this.lifecycleOwner = lifecycleOwner;
}

public void bind(Item item) {
binding.setItem(item);
binding.setVm(viewModel);
binding.executePendingBindings();
binding.setLifecycleOwner(lifecycleOwner);
}
}
}

我省略了 ViewModel, ListViewModel因为什么 vm.decrementItemQuantity(item)vm.incrementItemQuantity(item)本质上是调用模型来更新数据库中的数量:
@Query("UPDATE items SET quantity=quantity + 1 WHERE id=:itemId")
Completable incrementQuantity(int itemId);

@Query("UPDATE items SET quantity=quantity - 1 WHERE quantity > 1 AND id=:itemId")
Completable decrementQuantity(int itemId);

因此,虽然模型中的数量正在更新,但我不清楚我应该如何更新该特定 RecyclerView 项目的 UI 以反射(reflect)该更改。通常,当使用 LiveData 和 DataBinding 时,我会执行类似 itemQuantityLiveData.setValue(item.quantity) 的操作。这将立即反射(reflect)在 XML 中。但在这种情况下,我使用的是 bind(Item item)我的 ViewHolder 中的方法和 item对象作为变量而不是表达式传递给 DataBinding 布局。

我该如何解决这个问题?

最佳答案

没必要想太多。调用notifyItemChanged(position)在适配器实例上是缺失的部分。所以就变成了如何将 RecyclerView 项的索引传回适配器的问题。

编辑 rv_item.xml取一个额外的变量,position :

<data>
<variable
name="item"
type="com.mycodez.Item"/>

<!-- add this variable -->
<variable
name="position"
type="int"/>

<variable
name="vm"
type="com.mycodez.ListViewModel" />
</data>

此外,在同一个 XML 文件中,传递 positionvm onClick 触发的方法:
<Button
android:id="@+id/decrease_quantity"
android:onClick="@{() -> vm.decrementItemQuantity(item, position)}"/>

<Button
android:id="@+id/increase_quantity"
android:onClick="@{() -> vm.incrementItemQuantity(item, position)}"/>

然后 bind ListRvAdapter 中的方法 ViewHolder变成:
public void bind(Item item, int position) { // new argument
binding.setItem(item);
binding.setPosition(position); // pass position to the layout
binding.setVm(viewModel);
binding.executePendingBindings();
binding.setLifecycleOwner(lifecycleOwner);
}

在适配器的 onBindViewHolder 中传递新参数像这样:
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.bind(items.get(position), position);
}

最后,在 ListRvAdapter 中添加两个方法对于分别增加和减少的数量:
public void increaseQuantity(int position) {
Item item = items.get(position);
item.quantity += 1;
notifyItemChanged(position);
}

public void decreaseQuantity(int position) {
Item item = items.get(position);
item.quantity -= 1;
notifyItemChanged(position);
}

一切就绪后,当按钮 @+id/increase_quantity被点击, vm.incrementItemQuantity(item, position)被触发。在 MVVM 设置中,ViewModel 将具有 position 的 LiveData 事件对象。 :
public MutableLiveData<Event<Integer>> itemQuantityIncreased = new MutableLiveData<>(); 

并调用 vm.incrementItemQuantity(item, position)将设置该对象的值:
itemQuantityIncreased.setValue(new Event<>(position)) ;

最后,View 将在 ViewModel 的 itemQuantityIncreased 上有一个观察者。 LiveData 对象。因为 Event 会发送 RecyclerView 项目的位置,所以 View 可以得到它并调用 adapter.increaseQuantity(position)合适的地方。 adapter.decreaseQuantity(position)工作原理一样。

关于android - 如何更新 RecyclerView 项目内的绑定(bind)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57922438/

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