Android ListView 中的项目显示顺序错误。

huangapple go评论57阅读模式
英文:

Android ListView items displayed in wrong order

问题

我在更新我的Android应用程序中的ListView时遇到了问题。我已经搜索了解决方案并阅读了多个答案,但没有解决我的问题:

问题
我有一个ListView,显示2个项目,如下所示:

  • 项目1(位置0)
  • 项目2(位置1)

从源重新加载数据后,我仍然获得相同的2个项目,但在ListView中显示如下:

  • 项目2(位置0)
  • 项目2(位置1)

但是,当我点击新列表中的位置0时,它显示项目1的正确数据(点击位置1也显示项目2的正确数据)。

问题是它在位置0和位置1(两次)显示项目2。

以下是更新列表和设置适配器的代码:

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();
        ...
    }
}

以下是适配器代码:

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;
    }
}

ListView的宽度和高度都设置为父级ConstraintLayout中的match_parent,其中宽度=0dp(有父级)和高度=match_parent。

查看视频:
屏幕录制

感谢您的所有帮助。

我调试了应用程序。在清除schedulesList.clear()后,Fragment和BaseAdapter中都包含0个项目。从源中添加所有项目后,schedulesList中包含正确的项目,Fragment和BaseAdapter中也是如此。

我尝试使用clear和addAll将数据填充到适配器中作为单独的List对象。

英文:

I am having an issue updating the ListView in my Android application. I have searched for the solution and read multiple answers but none solved my issue:

Issue

I have a listview with 2 items displayed like this:

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

After reloading the data from the source I get the same 2 items, but in the listview it is displayed like this:

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

However, when I click on the position 0 in new list it shows correct data of Item 1 (click on position 1 it also shows correct data of Item 2).

The problem is that it displays Item 2 on position 0 and on position 1 (twice).

Here is the code where list is updated and adapter is setup:

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();
...
}

Here is Adapter code:

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;
}
}

ListView has width and height set to match_parent in parent ConstraintLayout where width=0dp (has parent) and height=match_parent

See the video:
screen recording

Thank you for all the help.

I debugged the app. After clearing schedulesList.clear() it contained 0 items in Fragment and also in BaseAdapter. After addAll items from the source it contained correct items in schedulesList both in Fragment and BaseAdapter.

I tried to fill the data in Adapter as separate List object using clear and addAll.

答案1

得分: 0

只使用RecyclerView
解决了我所有的问题。但我仍然不知道为什么上面的问题发生了。

英文:

I will answer my own question for the future visitors...

Just use RecyclerView

It solved all my issues. But I still do not know why the above problem happened.

huangapple
  • 本文由 发表于 2023年1月9日 01:49:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75050080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定