Sam
Sam

Reputation: 1229

Removing value from SharedPreferences inside CustomListAdapter issue

When a user adds a note this note gets saved into sharedpreferences. But when the user clicks on the image to remove the note this gets removed correctly and removed correctly from sharedpreferences. But when the user closes the app or changes tabs and come back the amount of notes removed gets replaces with the last note so it shows all duplicate notes in place of what was removed. I cannot figure this one out and am puzzled :/

Code:

import android.app.Activity;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.util.ArrayList;
import java.util.Map;
import static android.content.Context.MODE_PRIVATE;

public class CustomListAdapter extends ArrayAdapter<String> {

        private final Activity context;
        private ArrayList<String> notes = new ArrayList<>();
        private ImageView image;
        private int imageCross;
        TextView ruleNotesSet;
        final SharedPreferences FeedPref= PreferenceManager.getDefaultSharedPreferences(getContext());
        final SharedPreferences.Editor fd = FeedPref.edit();

        public CustomListAdapter(Activity context, ArrayList<String> notes, int imageCross) {
            super(context, R.layout.item,notes);
            this.context=context;
            this.notes = notes;
            this.imageCross = imageCross;
        }

        public View getView(final int position, View view, ViewGroup parent) {
            LayoutInflater inflater = context.getLayoutInflater();
            final View rowView = inflater.inflate(R.layout.item, null, false);
            ruleNotesSet = (TextView) rowView.findViewById(R.id.textView1);
            image = (ImageView) rowView.findViewById(R.id.icon);

            Glide.with(getContext())
                    .load(imageCross)
                    .skipMemoryCache(true)
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .into(image);


            image.setOnClickListener(new Button.OnClickListener(){
                @Override
                public void onClick(View v){
                    notes.remove(position);
                    fd.remove(Integer.toString(position));
                    fd.apply();
                    fd.commit();
                    notifyDataSetChanged();
                }
            });

            ruleNotesSet.setText(notes.get(position));
            fd.putString(Integer.toString(position), notes.get(position));
            fd.apply();
            fd.commit();

            return rowView;
        }

        public void addNote(String data) {
            notes.add(data);
        }
}

Logs:

10-30 13:22:30.053 2538-2538/org.app.random E/Logs: Adding a note{}
10-30 13:22:35.437 2538-2538/org.app.random E/Logs: Adding a note{0=note1}
10-30 13:22:44.927 2538-2538/org.app.random E/Logs: Adding a note{0=note1}
10-30 13:22:49.422 2538-2538/org.app.random E/Logs: Adding a note{0=note1}
10-30 13:22:51.187 2538-2538/org.app.random E/Logs: Adding a note{0=note1}
10-30 13:22:51.200 2538-2538/org.app.random E/Logs: Adding a note{0=note1}
10-30 13:22:51.211 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 1=note2}
10-30 13:22:51.222 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 1=note2, 2=note3}
10-30 13:23:06.252 2538-2538/org.app.random E/Logs: Change tabs/Close app{0=note1, 1=note2, 2=note3, 3=note4}
10-30 13:23:06.299 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 1=note2, 2=note3, 3=note4}
10-30 13:23:06.319 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 1=note2, 2=note3, 3=note4}
10-30 13:23:26.709 2538-2538/org.app.random E/Logs: Removing a note{0=note1, 2=note3, 3=note4}
10-30 13:23:26.716 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 2=note3, 3=note4}
10-30 13:23:26.721 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 2=note3, 3=note4}
10-30 13:23:26.747 2538-2538/org.app.random E/Logs: Adding a note{0=note1, 1=note3, 2=note3, 3=note4}
10-30 13:23:29.795 2538-2538/org.app.random E/Logs: Removing a note{1=note3, 2=note4, 3=note4}
10-30 13:23:29.799 2538-2538/org.app.random E/Logs: Adding a note{1=note3, 2=note4, 3=note4}
10-30 13:23:29.815 2538-2538/org.app.random E/Logs: Adding a note{0=note3, 1=note3, 2=note4, 3=note4}
10-30 13:23:38.491 2538-2538/org.app.random E/Logs: Change tabs/Close app{0=note3, 1=note4, 2=note4, 3=note4}
10-30 13:23:38.506 2538-2538/org.app.random E/Logs: Adding a note{0=note3, 1=note4, 2=note4, 3=note4}
10-30 13:23:38.521 2538-2538/org.app.random E/Logs: Adding a note{0=note3, 1=note4, 2=note4, 3=note4}

I've made the logs quite descriptive basically I add 4 notes, press back to remove the keypad this populates the sharedpreferences, I change tabs, I come back and remove notes and changing tabs again populates note 4 with the ones that are removed.

Edit:

What I need as I repopulate the view with what Is inside sharedpreferences is:

Start off with : app{0=note1, 1=note2, 2=note3, 3=note4}
Remove notes1 and note2: {1=note3, 2=note4}
When repopulating the view repopulate with only : {1=note3, 2=note4}
Instead what happens currently: {1=note3, 2=note4, 3=note4, 4=note4}

Edit:

Adding more logs as the code has changed per answer below:

10-30 17:12:31.527 12984-12984/org.random.app E/Logs: Notes in addNote{0=note 1}
10-30 17:12:31.554 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1}
10-30 17:12:34.400 12984-12984/org.random.app E/Logs: Notes in addNote{0=note 1, 1=note 2}
10-30 17:12:34.415 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 1=note 2}
10-30 17:12:36.525 12984-12984/org.random.app E/Logs: Notes in addNote{0=note 1, 1=note 2, 2=note 3}
10-30 17:12:36.542 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 1=note 2, 2=note 3}
10-30 17:12:38.273 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 1=note 2, 2=note 3}
10-30 17:12:38.295 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 1=note 2, 2=note 3}
10-30 17:12:45.983 12984-12984/org.random.app E/Logs: Removing a note{0=note 1, 2=note 3}
10-30 17:12:45.991 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}
10-30 17:12:45.994 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}
10-30 17:12:50.951 12984-12984/org.random.app E/Logs: Change tabs/Close app{0=note 1, 2=note 3}
10-30 17:12:50.975 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}
10-30 17:12:50.978 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}
10-30 17:12:54.390 12984-12984/org.random.app E/Logs: Removing a note{0=note 1, 2=note 3}
10-30 17:12:54.401 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}
10-30 17:12:57.466 12984-12984/org.random.app E/Logs: Change tabs/Close app{0=note 1, 2=note 3}
10-30 17:12:57.522 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}
10-30 17:12:57.531 12984-12984/org.random.app E/Logs: Notes in getView{0=note 1, 2=note 3}

Upvotes: 1

Views: 106

Answers (1)

alexscmar
alexscmar

Reputation: 421

I may found out why: Your adding back again string to SharedPrefernces in get View, each time it is called you have this code to be executed:

fd.putString(Integer.toString(position), notes.get(position));
fd.apply();
fd.commit();

just below line:

ruleNotesSet.setText(notes.get(position));

enter image description here

as you can see, when a Adapter builds the view to make it visible you're adding the same values back to SharedPreferences, if you have a large enough list the more extense it would be as scrolling upa/down will add new values to shared preferences.

Please comment them out and check the result.


New Approach

Create a class Note like this:

public class Note {

    private long key;
    private String note;


    public Note(String note) {
        this.note = note;
        this.key = System.currentTimeMillis();
    }

    public Note(long key, String note) {
        this.key = key;
        this.note = note;
    }

    public Note(String key, String note) {
        this.key = Long.parseLong(key);
        this.note = note;
    }

    public long getKey() {
        return key;
    }

    public String getNote() {
        return note;
    }

    public String getKeyAsString(){
        return String.valueOf(key);
    }
}

Then add this to your Activity (just for tests):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ArrayList<Note> notes = new ArrayList<Note>();
    try {
        notes.add(new Note(System.currentTimeMillis(), "Note 1"));
        Thread.sleep(2);
        notes.add(new Note(System.currentTimeMillis(), "Note 2"));
        Thread.sleep(2);
        notes.add(new Note(System.currentTimeMillis(), "Note 3"));
    } catch (Exception e) {

    }
    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);

    SharedPreferences.Editor edit = sp.edit();

    for (Note n : notes) {
        edit.putString(n.getKeyAsString(), n.getNote());
    }
}

And this method to load your notes from SharedPreferences

private List<Note> readNotes() {
    List<Note> notes = new ArrayList<Note>();
    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
    Map<String, ?> values = sp.getAll();

    for (String key : values.keySet()) {
        notes.add(new Note(key, (String) values.get(key)));
    }

    return notes;
}

An finally your custom ListAdapter:

public class CustomListAdapter extends ArrayAdapter<String> {

    private final Activity context;
    private ArrayList<Note> notes = new ArrayList<Note>();
    private ImageView image;
    private int imageCross;
    TextView ruleNotesSet;
    final SharedPreferences FeedPref= PreferenceManager.getDefaultSharedPreferences(getContext());
    final SharedPreferences.Editor fd = FeedPref.edit();

    public CustomListAdapter(Activity context, ArrayList<String> notes, int imageCross) {
        super(context, R.layout.item,notes);
        this.context=context;
        this.notes = notes;
        this.imageCross = imageCross;
    }

    public View getView(final int position, View view, ViewGroup parent) {
        Note note = notes.get(position);

        LayoutInflater inflater = context.getLayoutInflater();
        final View rowView = inflater.inflate(R.layout.item, null, false);
        ruleNotesSet = (TextView) rowView.findViewById(R.id.textView1);
        image = (ImageView) rowView.findViewById(R.id.icon);

        Glide.with(getContext())
                .load(imageCross)
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .into(image);


        image.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View v){
                Note n = (Note) v.getTag();
                notes.remove(n);
                fd.remove(n.getKeyAsString());
                fd.apply();
                fd.commit();
                notifyDataSetChanged();
            }
        });

        ruleNotesSet.setText(note.getNote());

        image.setTag(note);

        return rowView;
    }

    public void addNote(String data) {
        Note note = new Note(System.currentTimeMillis(), data);
        fd.putString(note.getKeyAsString(), note.getNote());
        fd.commit();
        notes.add(note);
        notifyDataSetChanged();
    }
}

I believe this will now work as you need.

Note: i put a timestamp as key to guarantee that keys will never repeat and, thus, will not overwrite existing key when adding new note.

Also notice that I added on each image the corresponding Note object as view tag to get it back later when user clicks to delete it so we get the correct note key.

Please try it out and let me know if it works for you.

Upvotes: 1

Related Questions