0

I need help here. So I've been tinkering with android studio and my app crashes everytime I type something in a textfield using onTextChanged and it prints this error in logcat java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1. How do I fix it? Thanks in advance.

Here's my NotesFragment.java:

package com.example.reminderapp;

import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;

import static android.R.layout.simple_list_item_1;

public class NotesFragment extends Fragment {
    View view;
    static ArrayList<String> notes = new ArrayList<>();
    static ArrayAdapter<String> arrayAdapter;
    FloatingActionButton fabfrNotes;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if(notes.size()==0)
        {
            view = inflater.inflate(R.layout.fragment_notes_empty, container, false);
            fabfrNotes = view.findViewById(R.id.fabNotes);
            fabfrNotes.setOnClickListener(v -> {
                Intent intent= new Intent(getContext(), NoteEditorActivity.class);
                startActivity(intent);
            });
        }
        else
        {
            view = inflater.inflate(R.layout.fragment_notes, container, false);
            ListView listView = view.findViewById(R.id.notesListView);

            arrayAdapter = new ArrayAdapter<>(view.getContext(), simple_list_item_1, notes);

            listView.setAdapter(arrayAdapter);
            listView.setOnItemClickListener((parent, view, i, id) -> {
                Intent intent = new Intent(getContext(), NoteEditorActivity.class);
                intent.putExtra("noteId", i);
                startActivity(intent);
            });
        }
        return view;
    }

}

and here's my NoteEditorAcitivity.java:

package com.example.reminderapp;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

import androidx.appcompat.app.AppCompatActivity;

public class NoteEditorActivity extends AppCompatActivity {

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

        EditText editTextTitle = findViewById(R.id.editTextNoteTitle);
        EditText editTextContent = findViewById(R.id.editTextNoteContent);

        Intent intent = getIntent();
        int noteId = intent.getIntExtra("noteId", -1);
        if(noteId!=-1){
            editTextTitle.setText(NotesFragment.notes.get(noteId));
        }

        editTextTitle.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                NotesFragment.notes.set(noteId, String.valueOf(s));
                NotesFragment.arrayAdapter.notifyDataSetChanged();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }
}

Here's my logcat:

java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1
        at java.util.ArrayList.set(ArrayList.java:455)
        at com.example.reminderapp.NoteEditorActivity$1.onTextChanged(NoteEditorActivity.java:36)
        at android.widget.TextView.sendOnTextChanged(TextView.java:10578)
        at android.widget.TextView.handleTextChanged(TextView.java:10685)
        at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:13568)
        at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1267)
        at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:576)
        at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:507)
        at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:37)
        at android.text.method.QwertyKeyListener.onKeyDown(QwertyKeyListener.java:228)
        at android.text.method.TextKeyListener.onKeyDown(TextKeyListener.java:141)
        at android.widget.TextView.doKeyDown(TextView.java:8466)
        at android.widget.TextView.onKeyDown(TextView.java:8240)
        at android.view.KeyEvent.dispatch(KeyEvent.java:2842)
        at android.view.View.dispatchKeyEvent(View.java:14247)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1959)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1959)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1959)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1959)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1959)
        at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1959)
        at com.android.internal.policy.DecorView.superDispatchKeyEvent(DecorView.java:476)
        at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1861)
        at android.app.Activity.dispatchKeyEvent(Activity.java:4085)
        at androidx.core.app.ComponentActivity.superDispatchKeyEvent(ComponentActivity.java:122)
        at androidx.core.view.KeyEventDispatcher.dispatchKeyEvent(KeyEventDispatcher.java:84)
        at androidx.core.app.ComponentActivity.dispatchKeyEvent(ComponentActivity.java:140)
        at androidx.appcompat.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:569)
        at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:59)
        at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.dispatchKeyEvent(AppCompatDelegateImpl.java:3054)
        at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:390)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:5947)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5815)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5310)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5485)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5542)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5518)
        at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:5676)
        at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:3179)
        at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:2721)
2021-03-02 15:49:39.538 17484-17484/com.example.reminderapp E/AndroidRuntime:     at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:2712)
        at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:3156)
        at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:143)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:335)
        at android.os.Looper.loop(Looper.java:183)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Elmer Matthew
  • 17
  • 1
  • 4
  • Do you understand the exception message? – blackapps Mar 02 '21 at 09:10
  • The very first time you are writing something into the textbox, onTextChanged is called. In that first time, noteId is -1. I assume the set you are calling which is getting -1 as first value is the cause of this issue. Maybe try to call it like this: NotesFragment.notes.set(noteId == -1 ? 0 : noteId, String.valueOf(s)); – Dan Baruch Mar 02 '21 at 09:11
  • you did not handle situtaion that notes is empty . if(notes.size()==0) { view = inflater.inflate(R.layout.fragment_notes_empty, container, false); fabfrNotes = view.findViewById(R.id.fabNotes); fabfrNotes.setOnClickListener(v -> { Intent intent= new Intent(getContext(), NoteEditorActivity.class); startActivity(intent); }); } here notes is empty and you try to set item in it. – behrad Mar 02 '21 at 09:13
  • @DanBaruch I've tried that. It gives me `java.lang.IndexOutOfBoundsException: Index: 0, Size: 0` – Elmer Matthew Mar 02 '21 at 09:16
  • 1
    Try to move your logic to "afterTextChanged" – Dan Baruch Mar 02 '21 at 09:17
  • @DanBaruch I've already fixed the issue. My problem was I insisted the app to keep updating the fragments while also asked the app to change its fragment layout when I type the title of my notes, and it's impossible since it's static (correct me if I'm wrong). So to fix it, I changed the code inside this `fabfrNotes.setOnClickListener` to only assign a value into notes ArrayList and refresh the fragment to get the new layout once the button is clicked. – Elmer Matthew Mar 02 '21 at 09:50

1 Answers1

0

You can get Exception ArrayIndexOutOfBoundsException when you are trying to access an item at index that doesn't exist. Let's say you have array of 10 elements with indexs from 0 to 9. If you try to access the 11th index or more you will get ArrayIndexOutOfBoundsException.

NotesFragment.notes.set(noteId, String.valueOf(s)); NotesFragment.arrayAdapter.notifyDataSetChanged();

The first line above is trying to update an item in array at index noteId, you are getting this error because no item exits at that index.

Please make sure that item exist at index noteId, you can add a break point there and inspect the value of noteId

  • Makes sense and this comment is the reason for me realizing this issue. I've fixed it my changed the codes inside `fabfrNotes.setOnClickListener` to these lines. `notes.add("Blank Notes "+notes.size());` `FragmentTransaction ft = getFragmentManager().beginTransaction();` `ft.detach(NotesFragment.this).attach(NotesFragment.this).commit();` Just so it will not be out of bound anymore. – Elmer Matthew Mar 02 '21 at 09:53