首页 > 解决方案 > RecyclerView 多种视图类型(View Holders)处理项选择计数状态

问题描述

我有一个分段的 recyclerview,其中包含标题标题和该 catergoty 下的项目。我有两个 viewHolders 一个用于标题,另一个用于该类别下的项目。这是我的适配器。

public class MenuAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {


public static final String TAG = MenuAdapter.class.getSimpleName();
private Context mContext;
private ItemClickListener itemClickListener;
private List<HeterogeneousObject> heterogeneousObjects;

public MenuAdapter(Context mContext, CartHelper helper) {
    this.mContext = mContext;
    heterogeneousObjects = new ArrayList<>();

}

public void itemClickListenerCallback(ItemClickListener itemClickListenerCallback) {
    this.itemClickListener = menuItemClickListenerCallback;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    if (viewType == 0) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_single_cuisine_rv, parent, false);
        return new MenuAdapterViewHolder(view);

    } else {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_single_cuisine_menu_items, parent, false);
        return new RecycledGridViewHolder(view);
    }

}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
    HeterogeneousObject object = heterogeneousObjects.get(position);
    if (object.getItemType() == 0) {
        if (object.getCuisine() != null) {
            MenuAdapterViewHolder holder = (MenuAdapterViewHolder) viewHolder;
            holder.cuisineName.setText(object.getCuisine().getCuisine_name());

        }
    } else {
        if (object.getMenuItem() != null) {
            RecycledGridViewHolder holder = (RecycledGridViewHolder) viewHolder;
            holder.dishName.setText(object.getMenuItem().getItemName());
            holder.dishPrice.setText(mContext.getString(R.string.rupee_symbol, object.getMenuItem().getItemPrice() * 0.01));

            if (object.getMenuItem().getIsVeg()) {
                holder.vegNonVegIndicator.setImageDrawable(mContext.getResources().getDrawable(R.drawable.veg_symbol));
                //holder.vegNonVegIndicator.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_veg_indicator));
            } else if (!object.getMenuItem().getIsVeg()) {
                holder.vegNonVegIndicator.setImageDrawable(mContext.getResources().getDrawable(R.drawable.non_veg_symbol));
                //holder.vegNonVegIndicator.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_non_veg_indicator));
            }
            Single<CartSelection> selection = cartHelper.getCartSelectionById(Long.parseLong(object.getMenuItem().getItemId()));
            selection.subscribe(new DisposableSingleObserver<CartSelection>() {
                @Override
                public void onSuccess(CartSelection cartSelection) {
                    if (cartSelection != null) {
                        holder.incDecButton.setNumber(cartSelection.getQty(), true);
                    }
                }

                @Override
                public void onError(Throwable e) {

                }
            });
            holder.bind(object.getMenuItem(), menuItemClickListener);
        }
    }

}


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

@Override
public int getItemViewType(int position) {
    super.getItemViewType(position);
    if (heterogeneousObjects.get(position).getItemType() == 0) {
        return 0;
    } else {
        return 1;
    }
}

}

这是我的视图支架 1

public class RecycledGridViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.tv_si_dish_name)
    TextView dishName;
    @BindView(R.id.tv_si_dish_price)
    TextView dishPrice;

    @BindView(R.id.btn_id_item_dish_grid)
    IncDecButton incDecButton;
    @BindView(R.id.iv_veg_non_veg_grid)
    AppCompatImageView vegNonVegIndicator;

    public RecycledGridViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    public void bind(final MenuItem menuItem, final MenuItemClickListener menuItemClickListener) {
        incDecButton.setOnButtonsClickedListener(new IncDecButton.OnButtonsClickedListener() {
            @Override
            public void onPlusClicked(int num) {

                if (menuItem.getCustomizable()) {
                    menuItemClickListener.onCustomizableItemClicked(menuItem, 1);
                    if (incDecButton.getNumber() == 0) {
                        incDecButton.setNumber(0, true);
                    }
                } else {
                    menuItemClickListener.onPlusButtonClicked(menuItem, num);
                }
            }

            @Override
            public void onMinusClicked(int num) {
                if (menuItem.getCustomizable()) {
                    menuItemClickListener.onCustomizableItemClicked(menuItem, 0);
                } else {
                    menuItemClickListener.onMinusButtonClicked(menuItem, num);
                }
            }
        });

}

查看支架 2

  class MenuAdapterViewHolder extends RecyclerView.ViewHolder {

    @BindView(R.id.tv_cuisine_name_menu_v2)
    TextView cuisineName;


    public MenuAdapterViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }
}

我正在维护一个项目计数状态,即 ViewHolder 1 中的列表项必须显示在 ROOM Db Dao 中 ViewHolder 之外的 IncDecButton 中,我查询它,因为每个项目都调用了 onBindViewHolder,但视图被回收并且项目计数得到放错地方了。

当我只有一个视图持有者时,即只有视图持有者 1,项目计数没有问题,但是当有 2 个视图持有者时,它会被回收并放错位置。我似乎真的不明白我做错了什么。

此代码仅适用于单个 Viewholder(单项类型 RecyclerView)。

标签: androidandroid-recyclerview

解决方案


a 中的视图在RecyclerView屏幕中消失时会被回收。您应该管理外部的状态ViewHolder并将其用于演示。您可以将计数的当前值存储在传递给适配器的项目数据中,然后在ViewHolder.

另一个重要的事情是始终设置值。如果你没有输入正确的值,ViewHolder将保持回收的视图,所以如果新单元格的计数为 0,只需将 0 放入绑定中。

希望能帮助到你。


推荐阅读