Search code examples
androidlistviewandroid-adapter

ListView adds duplicates of itself when changing the mode to light/dark


I have a problem with my android app for making notes. When I change mode (in app) from default to dark or light, the list duplicate itself. I have a custom adapter for ListView:

public View getView(int position, View listView, ViewGroup parent) {

    View v = listView;
    TextView tvTitle;
    TextView tvContent;

    Note n = noteList.get(position);
    Set<String> folders = n.getFolders();
    Set<String> foldersForChips = new HashSet<>(folders);
    foldersForChips.remove("Notes");
    foldersForChips.remove("All Notes");

    NoteHolder holder = new NoteHolder();

    if (listView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.row_layout, null);

        // view of the labels of the note ------------------------------------------------------
        holder.foldersChipGroup = (ChipGroup) v.findViewById(R.id.labels_of_note);
        holder.foldersChipGroup.setChipSpacingHorizontal(2);
        holder.foldersChipGroup.setClickable(false);
        holder.foldersChipGroup.setFocusable(false);
        for (String folder : foldersForChips) {
            Chip folderChip = new Chip(context);
            folderChip.setText(folder);
            folderChip.setTextSize(8);
            folderChip.setEnsureMinTouchTargetSize(false);
            folderChip.setHeight(40);
            folderChip.setChipMinHeight(10);
            folderChip.setBackgroundColor(Color.TRANSPARENT);
            folderChip.setChipBackgroundColor(null);

            ChipDrawable chipFolderDrawable = ChipDrawable.createFromAttributes(context, null,0, R.style.Widget_App_Chip);
            folderChip.setChipDrawable(chipFolderDrawable);

            holder.foldersChipGroup.addView(folderChip);
        }

        tvTitle = (TextView) v.findViewById(R.id.title);
        tvContent = (TextView) v.findViewById(R.id.content);

        holder.titleView = tvTitle;
        holder.contentView = tvContent;

        v.setTag(holder);
    } else {
        holder = (NoteHolder) v.getTag();
    }

    // view of the title and content of the note -----------------------------------------------
    if (n.getTitle() == "" || n.getTitle().isEmpty() || n.getTitle() == null ) {
        holder.contentView.setVisibility(View.VISIBLE);
        holder.contentView.setText(n.getContent());
        holder.contentView.setPadding(20,0,20, 0);
    } else if (n.getContent() == "" || n.getContent().isEmpty() || n.getContent() == null){
        holder.titleView.setVisibility(View.VISIBLE);
        holder.titleView.setText(n.getTitle());
        holder.titleView.setPadding(20,0,20, 0);
    } else {
        holder.titleView.setVisibility(View.VISIBLE);
        holder.titleView.setText(n.getTitle());
        holder.titleView.setPadding(20,0,20, 0);
        holder.contentView.setVisibility(View.VISIBLE);
        holder.contentView.setText(n.getContent());
        holder.contentView.setPadding(20,0,20, 0);
    }

    // background color ------------------------------------------------------------------------
    holder.cardView = v.findViewById(R.id.cardView);
    if (getItem(position).getBackgroundColor() != null) {
        holder.cardView.setCardBackgroundColor(Color.parseColor(getItem(position).getBackgroundColor()));
    }

    return v;
}

the button which change the mode in MainActivity.java:

FloatingActionButton fabLight = findViewById(R.id.light);
fabLight.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        themeChange.setVisibility(View.VISIBLE);

        SharedPreferences settingsPreferences = getApplicationContext().getSharedPreferences("com.example.settings", Context.MODE_PRIVATE);
        settingsPreferences.edit().putInt("Mode", AppCompatDelegate.MODE_NIGHT_NO).apply();

        listView.refreshDrawableState();
        noteAdapter.notifyDataSetChanged();
        //listView.setAdapter(noteAdapter);
    }
});

I found similar problem: ListView Added Duplicate item in list when screen orientation changes, but unfortunaltely the answers does not help me - I do not know how to implement them. I am new with android and I will be grateful for some guidance.

I tried refreshDrawableState() and setAdapter(noteAdapter) on my listView and notifyDataSetChanged() on adapter but it does not help. It is probable that I implement getView or my list in it wrong but I do not know how to improve that. Thank you in advance for all help.

In case - all files are in my GitHub repository: https://github.com/wmaterkowska/MyNotes_app.git


Solution

  • (My polish answer has been deleted so changed it to English)

    Method onCreate() is evoked when activity is launched first time, but also after screen configuration changes (and in some other situations) - for instance orientation or as in your case theme. There is no guarantee that this method will be called only single time, so if you create a list in here you should clear it to avoid duplication of the content every time method is called.

    notesToShow.clear(); //Add a line here
    
    for (Note note : allNotes) {
            if (note.getFolders().contains(folder) && !note.getFolders().contains("Recycle Bin")) {
                notesToShow.add(note);
            }
        }
    

    Hope it helps!