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

Android ListView条目显示重复、顺序异常问题求助

Android ListView 更新后显示重复数据问题

问题现象

原本ListView显示2个条目:

  • Item 1(position 0)
  • Item 2(position 1)

重新加载数据源后(数据源仍为这两个条目),ListView显示异常:

  • Item 2(position 0)
  • Item 2(position 1)

但点击position 0能获取Item1的正确数据,点击position1能获取Item2的正确数据,仅显示内容重复。

相关代码

Fragment 列表初始化与更新代码

public class FishTankFragment extends DeviceFragment {

    ...
    private final List<FishTankStatus.Schedule> schedulesList = new ArrayList<>();
    private ScheduleAdapter scheduleAdapter;
    ...
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ...
        scheduleAdapter = new ScheduleAdapter(view.getContext(), schedulesList);
        screenBinding.lvSchedules.setAdapter(scheduleAdapter);
        screenBinding.lvSchedules.setOnItemClickListener((parent, view1, position, id) -> {
            new ScheduleItemClickListener(this.getContext(), schedulesList.get(position), position);
        });
        ...
    }


    @Override
    public <T> void onResponse(T responseObject) {
        ...
        schedulesList.clear();
        schedulesList.addAll(data.getSchedules());
        scheduleAdapter.notifyDataSetChanged();
        ...
    }

Adapter 代码

public class ScheduleAdapter extends BaseAdapter {
    private ScheduleItemBinding itemBinding;
    private final List<FishTankStatus.Schedule> schedules;
    private final Context context;

    public ScheduleAdapter(@NonNull Context context, @NonNull List<FishTankStatus.Schedule> objects) {
        this.context = context;
        schedules = objects;
    }

    @Override
    public int getCount() {
        return schedules.size();
    }

    @Override
    public FishTankStatus.Schedule getItem(int position) {
        return schedules.get(position);
    }

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

    @Override
    public View getView(int position, View view, ViewGroup parent) {
        if (view == null) {
            itemBinding = ScheduleItemBinding.inflate(LayoutInflater.from(context));
            view = itemBinding.getRoot();
        }
        if (!schedules.isEmpty()) {
            String start = StringUtils.printTime(schedules.get(position).getStart());
            String end = StringUtils.printTime(schedules.get(position).getEnd());
            itemBinding.tvScheduleStart.setText(start);
            itemBinding.tvScheduleEnd.setText(end);
            FishTankStatus.Schedule schedule = schedules.get(position);
            for (String device : schedule.getDevices()) {
                switch (device) {
                    case "something":
                        itemBinding.ivYellowlightIcon.setVisibility(View.VISIBLE);
                        break;
                    case "something 1":
                        itemBinding.ivBluelightIcon.setVisibility(View.VISIBLE);
                        break;
                    case "something 2":
                        itemBinding.ivAirIcon.setVisibility(View.VISIBLE);
                }
            }

            if (schedules.get(position).getActive()) {
                ColorStateList white = ColorStateList.valueOf(
                        view.getResources().getColor(R.color.white, view.getContext().getTheme()));
                itemBinding.lySchedule.setBackground(ResourcesCompat.getDrawable(view.getResources(),
                        R.drawable.rectangle_p_light_8,
                        view.getContext().getTheme()));
                ...
            }
        }
        return view;
    }
}

已确认信息

  • 执行schedulesList.clear()后集合为空,addAll后Fragment和Adapter中的集合数据均正确
  • 尝试在Adapter中使用独立集合执行clear和addAll操作,问题依旧
  • ListView在父ConstraintLayout中宽高设为match_parent,父布局宽为0dp、高为match_parent

问题原因与解决方案

核心问题

  1. Binding实例复用错误:itemBinding是Adapter的成员变量,复用View时,新position的Binding会覆盖旧引用,导致所有复用View都使用最后一次创建的Binding实例,显示重复内容。
  2. 控件状态未重置:设置图标可见性、背景等状态时,未处理反向场景(如条目不含某设备时,未将对应图标设为GONE),导致旧条目状态残留。

修复后的Adapter实现

@Override
public View getView(int position, View view, ViewGroup parent) {
    ScheduleItemBinding binding;
    // 用View的Tag存储Binding,避免成员变量覆盖问题
    if (view == null) {
        binding = ScheduleItemBinding.inflate(LayoutInflater.from(context), parent, false);
        view = binding.getRoot();
        view.setTag(binding);
    } else {
        binding = (ScheduleItemBinding) view.getTag();
    }

    if (!schedules.isEmpty()) {
        FishTankStatus.Schedule schedule = schedules.get(position);
        String start = StringUtils.printTime(schedule.getStart());
        String end = StringUtils.printTime(schedule.getEnd());
        binding.tvScheduleStart.setText(start);
        binding.tvScheduleEnd.setText(end);

        // 先重置所有图标状态,避免复用旧数据
        binding.ivYellowlightIcon.setVisibility(View.GONE);
        binding.ivBluelightIcon.setVisibility(View.GONE);
        binding.ivAirIcon.setVisibility(View.GONE);

        for (String device : schedule.getDevices()) {
            switch (device) {
                case "something":
                    binding.ivYellowlightIcon.setVisibility(View.VISIBLE);
                    break;
                case "something 1":
                    binding.ivBluelightIcon.setVisibility(View.VISIBLE);
                    break;
                case "something 2":
                    binding.ivAirIcon.setVisibility(View.VISIBLE);
                    break;
            }
        }

        // 处理激活/非激活状态,必须覆盖两种场景
        if (schedule.getActive()) {
            ColorStateList white = ColorStateList.valueOf(
                    view.getResources().getColor(R.color.white, view.getContext().getTheme()));
            binding.lySchedule.setBackground(ResourcesCompat.getDrawable(view.getResources(),
                    R.drawable.rectangle_p_light_8,
                    view.getContext().getTheme()));
            // 补充激活状态的其他样式设置
        } else {
            // 恢复非激活状态的默认样式
            binding.lySchedule.setBackground(ResourcesCompat.getDrawable(view.getResources(),
                    R.drawable.your_default_background,
                    view.getContext().getTheme()));
            // 补充非激活状态的其他样式设置
        }
    }
    return view;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:35:30