0

Yes, I believe that there are many questions asking about this error, however I believe it relates to the following, shown below.

I have 3 ListViews mNote1, mNote2, mNote3 and they have all been passed through registerForContextMenu();. Then there is the onCreateContextMenu method:

please note at the top of the class activity there is, private static final int MENU_DELETE_ID = 1004; private int currentNoteId;

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        currentNoteId = (int) info.id;

        menu.add(0, MENU_DELETE_ID, 0, "Delete");

    }

and then the onContextItemSelected method:

@Override
    public boolean onContextItemSelected(MenuItem item) {

        if(item.getItemId() == MENU_DELETE_ID){
            NoteItem note = noteList.get(currentNoteId);
            NoteItem note1 = noteList1.get(currentNoteId);
            NoteItem note2 = noteList2.get(currentNoteId);
            datasource.remove(note);
            datasource1.remove(note1);
            datasource2.remove(note2);
            refreshDisplay(1001);
            refreshDisplay(1002);
            refreshDisplay(1003);

        }

        return super.onContextItemSelected(item);
    }

These, I believe, create the "Delete" option when the note on the ListView is held down and then the note is deleted when the delete option is selected. I believe in the onContextItemSelected method is where the error lies.

On the app, I create a note in the first ListView and I am not able to delete it as the app crashes. I can make make multiple notes in multiple ListViews but I am unable to delete them.

The NoteDataSource file is shown below, this creates the datasource1, datasource2, etc

public class NoteDataSource {

    private SharedPreferences notePrefs;

    public NoteDataSource(Context context, String PREFKEY){
        notePrefs = context.getSharedPreferences(PREFKEY, Context.MODE_PRIVATE);
    }

    public List<NoteItem> findAll(){

        Map<String, ?> noteMap = notePrefs.getAll();

        SortedSet<String> keys = new TreeSet<String>(noteMap.keySet());

        List<NoteItem> noteList = new ArrayList<NoteItem>();

        for (String key:keys) {
            NoteItem note = new NoteItem();
            note.setKey(key);
            note.setText((String) noteMap.get(key));
            noteList.add(note);
        }

        return noteList;

    }

    public boolean remove(NoteItem item){

        if (notePrefs.contains(item.getKey())){
            SharedPreferences.Editor editor = notePrefs.edit();
            editor.remove(item.getKey());
            editor.apply();
        }

        return true;
    }
    public boolean update(MealItem item){

        SharedPreferences.Editor editor = mealPrefs.edit();
        editor.putString(item.getKey(), item.getText());
        editor.apply();

        return true;
    }

}

The datasources are created in the onCreate method with datasource = new NoteDataSource(this, "note1"); and they are referenced in refreshDisplay method: Note, private ArrayAdapter<MealItem> adapter; 1 and 2 are initialized at the top of the class

private void refreshDisplay(int code) {
    notesList = datasource.findAll();
    notesList1 = datasource1.findAll();
    notesList2 = datasource2.findAll();

    if(code == 1001){
        adapter = new ArrayAdapter<NoteItem>(this, R.layout.list_item_layout, notesList);
        mNote1.setAdapter(adapter);
    }else if (code == 1002){
        adapter = new ArrayAdapter<NoteItem>(this, R.layout.list_item_layout, notesList1);
        mNote2.setAdapter(adapter);
    }else if(code == 1003){
        adapter = new ArrayAdapter<NoteItem>(this, R.layout.list_item_layout, notesList2);
        mNote3.setAdapter(adapter);
    }
}

The notesList are initialized at the top of the class, List<NoteItem> notesList; there are 3 of theese, notesList, notesList1 and notesList2

I'm not sure where the error is from, but I know that it is when I try to delete a note the app crashes and the notes I made are still there.

The error log says

java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
                                                                            at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
                                                                            at java.util.ArrayList.get(ArrayList.java:308)
                                                                            at com.example.notesapp.mainact.onContextItemSelected(MainAct.java:166)
                                                                            at android.app.Activity.onMenuItemSelected(Activity.java:2928)

What I think I am supposed to do is determine which datasource the note listview I have selected is in, as currently I am removing them all like this which is shown above in onContextItemSelected:

NoteItem note = noteList.get(currentNoteId);
                NoteItem note1 = noteList1.get(currentNoteId);
                NoteItem note2 = noteList2.get(currentNoteId);
                datasource.remove(note);
                datasource1.remove(note1);
                datasource2.remove(note2);
                refreshDisplay(1001);
                refreshDisplay(1002);
                refreshDisplay(1003);

any help would be greatly appreciated. thank you!

EDIT:

I have been following along with the tutorial on Lynda.com Building a Note-Taking App for Android (2013). I have created my app so it has 3 ListViews instead of one. The user is able to add notes to the a listview depending on what button they press. So if they press button1 and then enter the text and hit back it would appear on listview1, etc etc.

If I was to have one ListView, my program would work as I can only delete notes from the first ListView. The first ListView corresponds with datasource, and notesList, whereas the second and third ListView correspond with datasource1 datasource2, notesList1, notesList2 respectively.

To delete a note, you hold the ListView note down and then click delete. This works on the first ListView but not the second and third, the app crashes. The error log shows that. The following methods are the ones I use to create the delete button when held down and also to delete it.

please note at the top of the class activity there is, private static final int MENU_DELETE_ID = 1004; private int currentNoteId;

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        currentNoteId = (int) info.id;

        menu.add(0, MENU_DELETE_ID, 0, "Delete");

    }

and then the onContextItemSelected method:

@Override
    public boolean onContextItemSelected(MenuItem item) {

        if(item.getItemId() == MENU_DELETE_ID){
            NoteItem note = noteList.get(currentNoteId);
            NoteItem note1 = noteList1.get(currentNoteId);
            NoteItem note2 = noteList2.get(currentNoteId);
            datasource.remove(note);
            datasource1.remove(note1);
            datasource2.remove(note2);
            refreshDisplay(1001);
            refreshDisplay(1002);
            refreshDisplay(1003);

        }

        return super.onContextItemSelected(item);
    }

The app crashes at NoteItem note1 = noteList1.get(currentNoteId); and I am unsure on where to go from here.

EDIT 2:

Ok, so I Toasted the currentNoteId when I selected delete instead of deleting it. The first note was 0 and the second 1, etc. So I believe when I call notesList.get(currentNoteId) its getting the index from that array.

I guess I need some sort of way to signify which ListView I have selected it from, which would need to be in onCreateContextMenu which is shown at the very top of my question.

thc_123
  • 11
  • 1
  • Which line causes the error? – Code-Apprentice Feb 21 '16 at 02:35
  • I'm not sure, but it is in the method `onContextItemSelected`. I have outlined what I think I am supposed to do in my question. – thc_123 Feb 21 '16 at 02:42
  • The best place to start is the exact line where the error occurs. The stacktrace which you posted tells you `at com.example.notesapp.mainact.onContextItemSelected(MainAct.java:166)`. Since you have not posted the entire file and I cannot count to 166 even if you did, you need to indicate which line this is. – Code-Apprentice Feb 21 '16 at 02:44
  • This is my first proper project with Android and Java so I am unsure to do that? – thc_123 Feb 21 '16 at 02:46
  • Which part are you unsure about? – Code-Apprentice Feb 21 '16 at 02:46
  • I suggest reading [this](http://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors). – Code-Apprentice Feb 21 '16 at 02:47
  • Thanks. That makes it clearer, line 166 is `NoteItem note1 = notesList1.get(currentNoteId); ` – thc_123 Feb 21 '16 at 03:05
  • You need to start there and figure out what the values are in `notesList1` and `currentNoteId`. You also need to figure out why these values are different than what you expect. – Code-Apprentice Feb 21 '16 at 03:09
  • Nothing in the code you posted shows how `notesList1` is initialized nor how elements are added to it. – Code-Apprentice Feb 21 '16 at 03:10
  • notesList is initialized by `List notesList` at the top of the class and inside my refreshDisplay method, shown in my question there is `notesList = datasource.findAll();` – thc_123 Feb 21 '16 at 03:13
  • `List notesList;` is a **declaration** without any intialization. More importantly, `datasource.findAll()` seems to be returning an empty list. You will need to look in this method to find out why. – Code-Apprentice Feb 21 '16 at 03:18
  • I think you might be making this more difficult than it needs to be. What are you actually trying to do? – Code-Apprentice Feb 21 '16 at 03:20
  • See my edit. I tried to explain it. Basically notes in the second and third listview aren't being deleted. I want the program to know what ListView the selected note is from so it can be deleted from the array that is associated with that listview. – thc_123 Feb 21 '16 at 03:38
  • One problem is that it appears that you are attempting to remove notes from **all three** list views every time the user clicks on the Delete button. I doubt this is really what you want to do. You need some way to delete only the selected item from the list in which it belongs. – Code-Apprentice Feb 21 '16 at 03:41
  • Please read my edit, I believe I understand it a bit more now. – thc_123 Feb 21 '16 at 03:54
  • I'm confused why you want three ListViews. Is this supposed to be a learning exercise or do you have something in mind you actually want to do in a "real" app? – Code-Apprentice Feb 21 '16 at 04:10
  • This is just a small learning project/exercise. I just wanted to make a small app that lets me hold notes in for 3 modules of a subject I am doing in school. – thc_123 Feb 21 '16 at 04:13
  • I think there is a flaw in your design. Three separate list views on the same screen seems strange to me. Note taking apps which I have used have tags and/or categories that allow you to filter the list of notes. I can imagine other UI designs where each category is displayed on its own screen. This is definitely far from a "small learning exercise". I consider using `ListView` an intermediate topic rather than a beginner one. – Code-Apprentice Feb 21 '16 at 04:19
  • You should consider looking at some other more basic examples so you can get more experience with Android and the Java language itself. – Code-Apprentice Feb 21 '16 at 04:20

1 Answers1

0

In my onCreateContextMenu method I added the following line: viewNoteId = v.getId(); which got the id of the ListView that created the context menu.

Then I added a switch case element in the onContextItemSelected method as shown below:

    if (item.getItemId() == MENU_DELETE_ID){
        switch (viewNoteId){
            case R.id.listMonB:
                NoteItem note = notesList.get(currentNoteId);
                datasource.remove(note);
                refreshDisplay(1001);
                break;
            case R.id.listMonL:
                NoteItem note1 = notesList1.get(currentNoteId);
                datasource1.remove(note1);
                refreshDisplay(1002);
                break;
            case R.id.listMonD:
                NoteItem note2 = notesList2.get(currentNoteId);
                datasource2.remove(note2);
                refreshDisplay(1003);
                break;

        }
    }

It now works!

thc_123
  • 11
  • 1