【问题标题】:Multiple Spinner in a Recyclerview itemRecyclerview 项目中的多个微调器
【发布时间】:2021-05-15 08:07:52
【问题描述】:

我有一个包含 11 行数据项的回收站视图。我需要在每行修复两个微调器。即第二个 Spinner 数据应该依赖于第一个 Spinner 数据的变化。虽然我正在正确加载新的条目数据。当我来编辑第一个微调器数据时,加载正确完成并且已经存在的数据已正确修复。 但在第二个微调器中,它显示了最后加载的项目的数据。即所有第二个微调器中都设置了最后一行(第 11 行)微调器数据。如何解决这个问题?

下面的代码在recyclerViewAdapter的onBindViewHolder()方法下


 fortnightLookupList = gCache.getFortNightLookup();



        for(int i = 0; i<fortnightLookupList.size(); i++){
            funtioningSpinnerList.add(fortnightLookupList.get(i).getFunctioning());
        }
reasoningAdapter =
    new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, funtioningSpinnerList);
reasoningAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.functioningSpinner.setAdapter(reasoningAdapter);

if (entryStatus.equals(Constants.NEW)) {
    holder.functioningSpinner.setOnItemSelectedListener(new AdapterView . OnItemSelectedListener () {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            if (pos > 0) {
                remoteLocationEntryModelData.get(position).checkList =
                    funtioningSpinnerList.get(pos);
                //loadScoreSpinner(funtioningSpinnerList.get(pos), holder, position);

                scoreList.clear();

                for (int i = 0; i < fortnightLookupList.size(); i++) {
                    if (fortnightLookupList.get(i).getFunctioning().equals(funtioningSpinnerList.get(pos)) ) {
                        scoreList.add(fortnightLookupList.get(i).getScore());
                    }
                }

                scoreAdapter =
                    new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
                scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                holder.scoreSpinner.setAdapter(scoreAdapter);

            } else {
                remoteLocationEntryModelData.get(position).checkList = "$";
                scoreList.clear();
                scoreList.add(0, "---- select ----");
                scoreAdapter =
                    new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
                scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                holder.scoreSpinner.setAdapter(scoreAdapter);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

} else if (entryStatus.equals(Constants.EDIT)) {

    if (!TextUtils.isEmpty( String.valueOf( editList.getDescriptions().get(position).getLogId() ) ) ) {
        remoteLocationEntryModelData.get(position).logId =
            editList.getDescriptions().get(position).getLogId();
    }

    if (!TextUtils.isEmpty(editList.getDescriptions().get(position).getRemarks())) {
        holder.remarksEdt.setText(editList.getDescriptions().get(position).getRemarks());
    }



    holder.functioningSpinner.setSelection(
        funtioningSpinnerList.indexOf(
            editList.getDescriptions().get(position).getCheckList()
        )
    );

    holder.functioningSpinner.setOnItemSelectedListener(new AdapterView . OnItemSelectedListener () {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            if (pos > 0) {
                remoteLocationEntryModelData.get(position).checkList =
                    funtioningSpinnerList.get(pos);
                //loadScoreSpinner(funtioningSpinnerList.get(pos), holder, position);

                scoreList.clear();

                for (int i = 0; i < fortnightLookupList.size(); i++) {
                    if (fortnightLookupList.get(i).getFunctioning()
                            .equals(funtioningSpinnerList.get(pos))
                    ) {
                        scoreList.add(fortnightLookupList.get(i).getScore());
                    }
                }

                scoreAdapter =
                    new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
                scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                holder.scoreSpinner.setAdapter(scoreAdapter);

                //holder.scoreSpinner.setSelection(scoreList.indexOf(editList.getDescriptions().get(position).getScore()));

            } else {
                remoteLocationEntryModelData.get(position).checkList = "$";
                scoreList.clear();
                scoreList.add(0, "---- select ----");
                scoreAdapter =
                    new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
                scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                holder.scoreSpinner.setAdapter(scoreAdapter);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
}

注意 虽然我一步一步调试它,但它工作正常,但在运行时却不行

电流输出

预期输出

【问题讨论】:

  • 如果我理解正确,您有一个 RecyclerView,其中每个项目在项目内都有两个 Spinner,并附有 2 个 ArrayAdapter,对吗?您能否分享更多关于您从哪里获得用于填充两个 Spinner 的 ArrayAdapter 的列表的信息?
  • 是的,你是对的@hardartcore ....数组适配器的名称是 reasoningAdapterscoreAdapter 你可以找到这些。
  • funtioningSpinnerList 怎么样?它从何而来?你能分享你得到这个列表的代码吗?
  • 它就在推理适配器的上方。像下面fortnightLookupList = gCache.getFortNightLookup(); for(int i = 0; i&lt;fortnightLookupList.size(); i++){ funtioningSpinnerList.add(fortnightLookupList.get(i).getFunctioning()); }
  • 最好将其发布到主要答案,但我认为问题在于此列表的填充方式。

标签: java android android-studio android-recyclerview


【解决方案1】:

您将scoreList 保存在一个全局变量中并且从不重新定义该值

holder.functioningSpinner.setOnItemSelectedListener 中,您将获得scoreList.clear()

始终使用同一行设置 same List 引用 new ArrayAdapter&lt;&gt;(thisActivity, android.R.layout.simple_spinner_item, scoreList) 中的 all 适配器

使用scoreList.clear(),您将删除所有适配器中的数据并添加新值。

=> 是原因,为什么你会在所有列表项中看到最后一项的数据

注意虽然我逐步调试它,但它工作正常,但不是 运行时

原因是:

  • 在调试模式下你是。一切都是一步一步来的。
  • 在实际执行中,一切都在几毫秒内发生

如何解决

可能性 1. 重新创建列表而不是清除数据。你已经总是​​new ArrayAdapter了,为什么还要全局存储scoreList实例?

可能性 2. 将持有者作为自己的类,您在 onBindViewHolder 中所做的一切都在持有者类中。

例子:

生成基础持有者类

public abstract class BaseRecyclerBindingHolder<Item> extends RecyclerView.ViewHolder {

    public BaseRecyclerBindingHolder(View itemView) {
        super(itemView);
    }

    public abstract void configureView(Item item);
}

和基础适配器类

public abstract class BaseRecyclerBindingAdapter<Item, Holder extends BaseRecyclerBindingHolder<? super Item>, ItemBinding extends ViewBinding>
        extends RecyclerView.Adapter<Holder> {

    // Store a member variable for the items
    protected final List<Item> mItems;

    /**
     * @param items adapter items to show in UI
     */
    public BaseRecyclerBindingAdapter(List<Item> items) {
        mItems = items;
    }

    /**
     * Usually involves inflating a layout from XML and returning the holder
     *
     * @param parent   container of adapter items
     * @param viewType type of item
     * @return ViewHolder for adapter item
     */
    @NonNull
    @Override
    public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // Inflate the custom layout
        ItemBinding itemView = getLayoutResource(LayoutInflater.from(parent.getContext()), parent);

        return getHolder(itemView, viewType);
    }

    /**
     * Involves populating data into the item through holder
     *
     * @param holder   ViewHolder class to construct UI for item
     * @param position item position in adapter
     */
    @Override
    public void onBindViewHolder(@NonNull Holder holder, int position) {
        Item item = mItems.get(position);

        holder.configureView(item);
    }

    /**
     * @return count of items in adapter
     */
    @Override
    public int getItemCount() {
        return mItems.size();
    }

    /**
     * gets the type of item of specified position in adapter
     *
     * @param position item position
     * @return default 0
     */
    @Override
    public abstract int getItemViewType(int position);

    /**
     * Usually use:
     * ItemBinding.inflate(layoutInflater);
     * To use parents properties of width and height, make this way:
     * ItemBinding.inflate(layoutInflater, parent, false);
     *
     * @param layoutInflater the inflater to set XMl to view
     * @param parent         container of adapter items
     * @return ViewBinding element with access to all views with IDs in UI
     */
    protected abstract ItemBinding getLayoutResource(LayoutInflater layoutInflater, ViewGroup parent);

    /**
     * based on viewType gets the ViewHolder class for the item
     *
     * @param viewBinding element with access to all views with IDs in UI
     * @param viewType    type of item
     * @return ViewHolder for adapter item
     */
    protected abstract Holder getHolder(ItemBinding viewBinding, int viewType);

    /**
     * @param position item position
     * @return item on specified position in adapter
     */
    public Item getItem(int position) {
        return mItems.get(position);
    }

    /**
     * @return list of items in adapter
     */
    public List<Item> getItems() {
        return mItems;
    }
}

现在为您的目的生成特定的持有人

public class YourHolderName extends BaseRecyclerBindingHolder<YourHolderItem> {

    private final YourHolderBinding binding;

    // add here more variable that you needs from adapter
    public YourHolderName(YourHolderBinding binding) {
        super(binding.getRoot());

        this.binding = binding;
    }

    @Override
    public void configureView(YourHolderItem yourHolderItem) {
        // here comes what you make i your holder
    }
}

至少定义一个超级简单且小巧的适配器

public class YourAdapterName extends BaseRecyclerBindingAdapter<YourHolderItem, YourHolderName, YourHolderBinding> {

    /**
     * @param yourHolderItem adapter items to show in UI
     */
    // add more parameters if needed
    public YourAdapterName(List<YourHolderItem> yourHolderItems) {
        super(yourHolderItems);
    }

    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    protected YourHolderBinding getLayoutResource(LayoutInflater layoutInflater, ViewGroup parent) {
        return YourHolderBinding.inflate(layoutInflater, parent, false);
    }

    @Override
    protected YourHolderName getHolder(YourHolderBinding viewBinding, int viewType) {
        // add more parameters if needed
        return new YourHolderName(viewBinding);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多