androidlistviewswiperefreshlayout

Android ListView items displayed in wrong order


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:

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

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.


Solution

  • 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.