Q:

ListView is mixing entries

I have a strange problem and i cant figure out what's the problem. I have the following simple layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/measuredata_list_row_parent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:divider="@null"
        android:dividerHeight="5dp"
        android:listSelector="@android:color/transparent"
        android:textColor="@color/textcolorprimary" />

</LinearLayout>

The Adapter i use is the following:
public class MeasureDataListAdapter extends ArrayAdapter<MeasureDataListEntry> {

    public MeasureDataListAdapter(Context context, List<MeasureDataListEntry> entries) {
        super(context, R.layout.activity_measuredata_list_fragment_row, entries);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final MeasureDataListEntry entry = this.getItem(position);

        ViewHolder viewHolder = null;
        LayoutInflater inflater = null;

        if(convertView == null) {
            inflater = LayoutInflater.from(this.getContext());
            convertView = inflater.inflate(R.layout.activity_measuredata_list_fragment_row, parent, false);

            viewHolder = new ViewHolder();
            viewHolder.textViewTime = (TextView) convertView.findViewById(R.id.measuredata_list_row_textview_time);
            viewHolder.textViewValue = (TextView) convertView.findViewById(R.id.measuredata_list_row_textview_value);
            viewHolder.textViewMood = (TextView) convertView.findViewById(R.id.measuredata_list_row_textview_mood);
            viewHolder.layoutMealTime = (LinearLayout) convertView.findViewById(R.id.measuredata_list_row_layout_mealtime);
            viewHolder.textViewMealTime = (TextView) convertView.findViewById(R.id.measuredata_list_row_textview_mealtime);
            viewHolder.imageButtonMeal = (ImageButton) convertView.findViewById(R.id.measuredata_list_row_imagebutton_meal);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.textViewTime.setText(Helper.getDateTimePattern(this.getContext(), entry.getTime()));
        viewHolder.textViewValue.setText(entry.getValue() + " " + Helper.getUnitForShortcut(this.getContext(), entry.getUnit()));
        viewHolder.textViewMood.setText(Helper.getMood(this.getContext(), entry.getMood()));

        String mealTime = Helper.getMealTimeForShortcut(this.getContext(), entry.getMealTime());

        if(mealTime != null && !mealTime.trim().isEmpty()) {
            viewHolder.layoutMealTime.setVisibility(LinearLayout.VISIBLE);
            viewHolder.textViewMealTime.setText(mealTime);
        }

        File imageFile = entry.getImageFile();

        if(imageFile != null) {
            viewHolder.imageButtonMeal.setVisibility(ImageButton.VISIBLE);
        }

        return convertView;
    }

    private static class ViewHolder {
        private TextView textViewTime = null;
        private TextView textViewValue = null;
        private TextView textViewMood = null;
        private LinearLayout layoutMealTime = null;
        private TextView textViewMealTime = null;
        private ImageButton imageButtonMeal = null;
    }
}

And this is the Fragment for the List:
public class MeasureDataListFragment extends DiagramBaseFragment implements OnDateSetListener, MeasureDataGetCallback {
    private MeasureDataListAdapter measureDataListAdapter = null;
    private ListView listRowParent = null;
    private List<MeasureDataListEntry> measureDataListEntries = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setRetainInstance(true);
        this.setHasOptionsMenu(true);

        this.sessionLoginPreferences = new SessionLoginPreferences(this.getActivity());
        this.sessionLoginSingleton = SessionLoginSingleton.getInstance(this.getActivity());
        this.sessionProfilePreferences = new SessionProfilePreferences(this.getActivity());
        this.sessionMeasureDataPreferences = new SessionMeasureDataPreferences(this.getActivity());
        this.sessionMeasureDataListSingleton = SessionMeasureDataListSingleton.getInstance();
        this.sessionMeasureDataListFavouriteSingleton = SessionMeasureDataListFavouriteSingleton.getInstance();

        if(this.sessionMeasureDataListSingleton.getMeasureDataList() == null) {
            this.sessionMeasureDataListSingleton.setMeasureDataList(new MeasureDataList());
        }

        if(this.sessionMeasureDataListFavouriteSingleton.getMeasureDataList() == null) {
            this.sessionMeasureDataListFavouriteSingleton.setMeasureDataList(new MeasureDataList());
        }

        this.measureDataListEntries = new ArrayList<MeasureDataListEntry>();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.activity_measuredata_list_fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        this.measureDataListAdapter = new MeasureDataListAdapter(this.getActivity(), this.measureDataListEntries);

        this.listRowParent = (ListView) view.findViewById(R.id.measuredata_list_row_parent);
        this.listRowParent.setAdapter(this.measureDataListAdapter);
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if((this.sessionMeasureDataListFavouriteSingleton != null || this.sessionMeasureDataListSingleton != null)) {
            this.fragmentBecameVisible();
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.diagram_activity_actions, menu);

        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            this.getActivity().finish();
            return true;
        case R.id.action_search:
            this.showDatePicker(this.getResources().getString(R.string.text_from));
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        monthOfYear = (monthOfYear + 1);

        if(view == null && year == 0 && monthOfYear == 0 && dayOfMonth == 0) {
            this.from = true;
        } else {
            if(from) {
                this.fromDate = dayOfMonth + "." + monthOfYear + "." + year;
                this.from = false;

                this.showDatePicker(this.getResources().getString(R.string.text_to));
            } else {
                this.toDate = dayOfMonth + "." + monthOfYear + "." + year;
                this.from = true;

                this.getMeasureData(this.fromDate, this.toDate);
            }
        }
    }

    @Override
    public void onMeasureDataGetCompleted(StatusMeasureDataGet status, MeasureDataGetPOJO measureDataGetPOJO) {
        switch(status) {
            case MEASUREDATA_TRANSFERED: {
                if(this.favourite) {
                    this.sessionMeasureDataListFavouriteSingleton.setMeasureDataList(measureDataGetPOJO);
                } else {
                    this.sessionMeasureDataListSingleton.setMeasureDataList(measureDataGetPOJO);
                    this.saveLastMeasureData();
                }

                this.fragmentBecameVisible();
            } break;
            case ERROR_CONNECTION_FAILED: {
                String title = this.getResources().getString(R.string.text_error);
                String message = this.getResources().getString(R.string.text_connection_failed);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
            case ERROR_IO_EXCEPTION: {
                String title = this.getResources().getString(R.string.text_error);
                String message = this.getResources().getString(R.string.text_io_exception);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
            case ERROR_JSON_EXCEPTION: {
                String title = this.getResources().getString(R.string.text_error);
                String message = this.getResources().getString(R.string.text_json_exception);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
            case ERROR_NO_DATA_FOUND: {
                String title = this.getResources().getString(R.string.text_error);
                String message = this.getResources().getString(R.string.text_not_data_found);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
            case ERROR_PROTOCOL_EXCEPTION: {
                String title = this.getResources().getString(R.string.text_error);
                String message = this.getResources().getString(R.string.text_protocol_exception);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
            case ERROR_WRONG_PARAMETERS: {
                String title = this.getResources().getString(R.string.text_error);
                String message = this.getResources().getString(R.string.text_wrong_parameters);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
            case ERROR_WRONG_USER_OR_PW: {
                String title = this.getResources().getString(R.string.text_input_error);
                String message = this.getResources().getString(R.string.text_wrong_mail_or_pw);

                DialogManager.showAlertDialog(title, message, this.getFragmentManager());
            } break;
        }
    }

    private void fragmentBecameVisible() {
        this.initAdapter();

        if(this.measureDataListAdapter != null) {
            this.measureDataListAdapter.notifyDataSetChanged();
        }
    }

    /**
     * 
     */
    protected void initAdapter() {
        this.measureDataListEntries.clear();

        if(this.favourite) {
            measureDataList = this.sessionMeasureDataListFavouriteSingleton.getMeasureDataList();
        } else {
            measureDataList = this.sessionMeasureDataListSingleton.getMeasureDataList();
        }

        Collections.sort(measureDataList.getMeasureDataListEntries());

        for(MeasureDataListEntry measureDataListEntry : measureDataList.getMeasureDataListEntries()) {
            this.measureDataListEntries.add(measureDataListEntry);
        }
    }

    protected void saveLastMeasureData() {
        String email = this.getEmail();

        MeasureDataListEntry measureData = this.sessionMeasureDataPreferences.getMeasureData(this.getEmail());

        int index = (this.sessionMeasureDataListSingleton.getMeasureDataList().getMeasureDataListEntries().size() - 1);

        MeasureDataListEntry measureDataListEntry = this.sessionMeasureDataListSingleton.getMeasureDataList().getMeasureDataListEntries().get(index);

        if(measureDataListEntry.compareTo(measureData) > 0) {
            this.sessionMeasureDataPreferences.setMeasureData(email, measureDataListEntry);
        }
    }

    protected void getMeasureData(final String fromDate, final String toDate) {
        String email = this.getEmail();
        String password = this.getPassword();

        FragmentTransaction fragmentTransaction = this.getFragmentManager().beginTransaction();
        MeasureDataGetTask measureDataGetTask = new MeasureDataGetTask(email, password, fromDate, toDate);
        MeasureDataGetDialogFragment measureDataGetDialogFragment = new MeasureDataGetDialogFragment(measureDataGetTask, this);

        measureDataGetDialogFragment.show(fragmentTransaction, null);
    }

    protected void showDatePicker(String title) {
        FragmentTransaction fragmentTransaction = this.getFragmentManager().beginTransaction();
        DatePickerDialogFragment datePickerDialogFragment = new DatePickerDialogFragment(this, title);

        datePickerDialogFragment.show(fragmentTransaction, null);
    }
}

Now to the problem
When i fill the list with data everything seems to be alright and it contains 19 entries. Only the last entry of the list contains an image. As long as i dont scroll to the last entry with the image everything stays alright.
But after i scrolled to the last entry with the image, the data somehow gets totally mixed up. When i now scroll up again suddenly also the 4th the 9th and the 14th entry contains an image and exactly the same image like the last entry (two entries should not contain the same image).
So my question is: how can it be possible that the list gets corrupted after i scroll to an entry with an image? How can the image of the last entry suddenly be copied to other entries?

A:

you should simply add else statement to your getView() method like this:  
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final MeasureDataListEntry entry = this.getItem(position);
    //every thing like before...
    if(imageFile != null) {
        viewHolder.imageButtonMeal.setVisibility(ImageButton.VISIBLE);
    }else{
       viewHolder.imageButtonMeal.setVisibility(ImageButton.INVISIBLE); //or GONE
    }

    return convertView;
}  

it happen because you VISIBLE imageView when you show last row but never INVISIBLE that in other rows, so when you visit last row it's visibility change to VISIBLE and it will same for other rows

