You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView条目嵌套双联动Spinner时第二个Spinner全显最后一行数据如何解决

RecyclerView多行Spinner联动时第二个Spinner全部显示最后一行数据的解决方案

问题根源

  • 代码中的scoreList是适配器全局的成员变量,所有行的第二个Spinner的ArrayAdapter都绑定了同一个列表实例。任意行触发Spinner选中事件时调用scoreList.clear()修改内容,所有绑定了该列表的Adapter都会同步刷新,最终所有行的第二个Spinner都会显示最后一次修改(第11行联动触发)的列表数据。
  • 编辑场景下仅设置了第一个Spinner的选中值,联动加载完第二个Spinner的列表后没有主动回显之前保存的评分值。
  • 单步调试时执行速度慢,每一行的联动逻辑执行完成才会处理下一行的绑定,看起来逻辑正常;正常运行时setSelection触发的onItemSelected是异步排队执行的,11行的修改操作全部作用于同一个全局列表,最终只剩最后一行的结果。

修复步骤

  1. 不要使用全局的scoreList成员变量,每次生成第二个Spinner的数据源时都创建独立的局部ArrayList实例,避免所有行共用同一个数据源。
  2. 编辑场景下,第二个Spinner的列表加载完成后,主动调用setSelection回显之前保存的评分数据。
  3. 注意funtioningSpinnerList如果是全局成员变量,每次onBindViewHolder执行时都要先清空再添加数据,避免多次绑定后数据重复。

修复后代码示例

// 建议把fortnightLookupList和funtioningSpinnerList的提取逻辑放到适配器初始化方法中,不要每次onBind都执行,提升性能
fortnightLookupList = gCache.getFortNightLookup();
// 如果funtioningSpinnerList是全局变量,每次onBind先清空,避免数据重复
funtioningSpinnerList.clear();
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) {
            // 每次创建独立的scoreList,不要用全局变量
            List<String> scoreList = new ArrayList<>();
            if (pos > 0) {
                remoteLocationEntryModelData.get(position).checkList = funtioningSpinnerList.get(pos);
                for (int i = 0; i < fortnightLookupList.size(); i++) {
                    if (fortnightLookupList.get(i).getFunctioning().equals(funtioningSpinnerList.get(pos)) ) {
                        scoreList.add(fortnightLookupList.get(i).getScore());
                    }
                }
            } else {
                remoteLocationEntryModelData.get(position).checkList = "$";
                scoreList.add(0, "---- select ----");
            }
            ArrayAdapter<String> 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());
    }

    // 先设置选中监听器,再设置第一个Spinner的选中项,保证联动逻辑正常触发
    holder.functioningSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            // 每次创建独立的scoreList,不要用全局变量
            List<String> scoreList = new ArrayList<>();
            if (pos > 0) {
                remoteLocationEntryModelData.get(position).checkList = funtioningSpinnerList.get(pos);
                for (int i = 0; i < fortnightLookupList.size(); i++) {
                    if (fortnightLookupList.get(i).getFunctioning().equals(funtioningSpinnerList.get(pos)) ) {
                        scoreList.add(fortnightLookupList.get(i).getScore());
                    }
                }
                ArrayAdapter<String> scoreAdapter = new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
                scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                holder.scoreSpinner.setAdapter(scoreAdapter);
                // 编辑场景主动回显第二个Spinner的选中值
                String savedScore = editList.getDescriptions().get(position).getScore();
                int scorePos = scoreList.indexOf(savedScore);
                if(scorePos >=0){
                    holder.scoreSpinner.setSelection(scorePos);
                }
            } else {
                remoteLocationEntryModelData.get(position).checkList = "$";
                scoreList.add(0, "---- select ----");
                ArrayAdapter<String> 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) {

        }
    });
    // 监听器设置完成后再设置第一个Spinner的选中项,触发联动
    holder.functioningSpinner.setSelection(funtioningSpinnerList.indexOf(editList.getDescriptions().get(position).getCheckList()));
}

额外优化建议

  • 把fortnightLookupList的获取和funtioningSpinnerList的生成逻辑放到适配器的构造方法中执行,不要每次onBindViewHolder都重复遍历,减少不必要的性能消耗。
  • 如果列表数据量较大,可以考虑对fortnightLookupList做分类缓存,比如用HashMap<String, List<String>>保存每个functioning对应的score列表,避免每次联动都遍历整个列表。

内容的提问来源于stack exchange,提问作者Viswa Sundhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 21:27:03