Aham_Uzoma
Aham_Uzoma

Reputation: 185

getAdapterPosition() throws an Exception [android]

I have tried my best to understand the issue around this single problem. I am creating a function which involves editing contents(Items) of a recyclerview. It works just fine when editing one row but throws an ArrayIndexOutOfBounds exception when editing another row in the recyclerview.

This code is the source of the error.

((ClassListOnSetup) context).editClassnameAt(classes.get(getAdapterPosition()).getId(), getAdapterPosition(), classesBean);

I think the getAdapterPosition() method could be throwing this error:

Here is the editClassnameAt() method for more reference purposes:

public void editClassnameAt(long id,int position, String classname ){
    demeaSQL.updateAclass(id,classname);

    classListOnSetupRecyclerAdapter.notifyItemChanged(position);
    classListOnSetupRecyclerAdapter.notifyDataSetChanged();
    displayClassList();
}

Error message at LogCat

java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
at java.util.ArrayList.get(ArrayList.java:413) at com.example.demeainc.demea.ClassListOnSetupRecyclerAdapter$ClassListOnSetupViewHolder$2$2.onClick(ClassListOnSetupRecyclerAdapter.java:87) at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:162)

What am I getting wrong. Any help please?

For those of you that will like to review the full code,
Here is my Adapter class full code:

public class ClassListOnSetupRecyclerAdapter extends RecyclerView.Adapter<ClassListOnSetupRecyclerAdapter.ClassListOnSetupViewHolder {

    //simple list of classes(mDataSet for Adapter)
    private List<ClassesBean> listClasses;
    private Context mContext;

    public class ClassListOnSetupViewHolder extends RecyclerView.ViewHolder {

        public TextView textView_classname;
        public Button delete_button_classsetup;

        public ClassListOnSetupViewHolder(final Context context, View itemView, final List<ClassesBean> classes) {
            super(itemView);

            textView_classname = itemView.findViewById(R.id.textView_classname);
            delete_button_classsetup = itemView.findViewById(R.id.delete_button_classsetup);

            delete_button_classsetup.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    //  if(view.equals(delete_button_classsetup)) {
                        Log.i("Deletes", "Button pressed");
                        long id = classes.get(getAdapterPosition()).getId();

                        ((ClassListOnSetup) context).removeAt(getAdapterPosition(), classes.get(getAdapterPosition()).getId());
                        Toast.makeText(context, "You Clicked ID = " + id, Toast.LENGTH_SHORT).show();
                }
            });

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

                    View promptView = inflater.inflate(R.layout.edit_class, null);

                    AlertDialog.Builder alertDialogueBuilder = new AlertDialog.Builder(mContext);

                    alertDialogueBuilder.setView(promptView);

                    final EditText editText = promptView.findViewById(R.id.edittable_className);
                    editText.setText((listClasses.get(getAdapterPosition()).getClasses_name()));

                    alertDialogueBuilder.setCancelable(false).setPositiveButton("Update", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            // long id = classes.get(getAdapterPosition()).getId();

                            String classesBean = editText.getText().toString();

                            try {
                                /**This is as a result of trying to find a solution**/
                                //long classesArraySize = classes.size();
                                // while (classes.get(getAdapterPosition()).getId() < classesArraySize) 

                                /**Source of error**/
                                ((ClassListOnSetup) context).editClassnameAt(classes.get(getAdapterPosition()).getId(), getAdapterPosition(), classesBean);
                            } catch (ArrayIndexOutOfBoundsException exception){
                                Log.i("Errore", String.valueOf(exception));
                            }
                        }
                    }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            dialogInterface.cancel();
                        }
                    });

                    AlertDialog alert = alertDialogueBuilder.create();
                    alert.show();
                }
            });
        }
    }

    public ClassListOnSetupRecyclerAdapter(Context context, List<ClassesBean> classes){

        mContext = context;
        listClasses = classes;
    }

    @Override
    public ClassListOnSetupRecyclerAdapter.ClassListOnSetupViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_classesname_recycler,parent,false);

        return new ClassListOnSetupViewHolder(mContext,itemView,listClasses);
    }

    @Override
    public void onBindViewHolder(ClassListOnSetupViewHolder holder, final int position) {

        holder.textView_classname.setText(listClasses.get(position).getClasses_name());
    }

    @Override
    public int getItemCount() {
        Log.v(ClassListOnSetupRecyclerAdapter.class.getSimpleName(),"ListClasses"+listClasses.size());
        return listClasses.size();
    }
}

And my JavaBean Class called ClassesBean

public class ClassesBean {

    private Long id;
    private int classes_item_index;
    private String classes_name;
    private String classes_codename;
    private String classes_sections;
    private String classes_teachers;
    private String classes_students;

    public int getClasses_item_index() {

        return classes_item_index;
    }

    public void setClasses_item_index(int classes_item_index) {
        this.classes_item_index = classes_item_index;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getClasses_name() {

        return classes_name;
    }

    public void setClasses_name(String classes_name) {
        this.classes_name = classes_name;
    }

    public String getClasses_codename() {
        return classes_codename;
    }

    public void setClasses_codename(String classes_codename) {
        this.classes_codename = classes_codename;
    }

    public String getClasses_sections() {
        return classes_sections;
    }

    public void setClasses_sections(String classes_sections) {
        this.classes_sections = classes_sections;
    }

    public String getClasses_teachers() {
        return classes_teachers;
    }

    public void setClasses_teachers(String classes_teachers) {
        this.classes_teachers = classes_teachers;
    }

    public String getClasses_students() {
        return classes_students;
    }

    public void setClasses_students(String classes_students) {
        this.classes_students = classes_students;
    }



}

Upvotes: 1

Views: 1272

Answers (2)

Minas Mina
Minas Mina

Reputation: 2107

My original answer stated that you should add the listeners in onBindViewHolder(). This worked but it was not the most optimal solution, as new listener objects are created every time onBindViewHolder() is called.

Adding the listeners in the constructor is correct, however, getAdapterPosition() can sometimes return -1 (RecyclerView.NO_POSITION).

The solution is to check if getAdapterPosition() == RecyclerView.NO_POSITION and ignore the call if it's true.

 public ClassListOnSetupViewHolder(final Context context, View itemView, final List<ClassesBean> classes) {

    super(itemView);

    delete_button_classsetup = itemView.findViewById(R.id.delete_button_classsetup);

    delete_button_classsetup.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            int adapterPosition = getAdapterPosition();
            if (adapterPosition == RecyclerView.NO_POSITION) {
                return;
            }

            Log.i("Deletes", "Button pressed");
            long id = classes.get(adapterPosition).getId();

            ((ClassListOnSetup) context).removeAt(adapterPosition, classes.get(adapterPosition).getId());
            Toast.makeText(context, "You Clicked ID = " + id, Toast.LENGTH_SHORT).show();
        }
    });

    // ...
 }

Upvotes: 3

TangXianQiang
TangXianQiang

Reputation: 136

getAdapterPosition() return -1.It means Adapter gets a NO_POSITION,and it always happened when you call notifyDataSetChanged().so,you can edit the log of getAdapterPosition().At the same time,you should make sure getAdapterPosition() != -1 or getAdapterPosition() whthin the index of list before you call list.get(index).By the way,we always set click listener in the onBindViewHolder() rather than the constructor of ViewHolder.

Upvotes: 1

Related Questions