2

I am trying to delete the selected item from a ListView and the Problem is that when I delete the selected content and refresh the Adapter the position of the remaining content changes, so because of that at some point of deleting the content again it gives IndexOutOfBoundsException. Can anyone tell me how to solve this problem?

Here is my code for deleting the selected item.

    public View getView(final int position, View convertView, ViewGroup parent) {

    View view = null;
    if (convertView == null) {
        LayoutInflater inflator = mActivity.getLayoutInflater();
        view = inflator.inflate(R.layout.main, null);

        final ViewHolder viewholder = new ViewHolder();
        viewholder.tvTitle = (TextView) view.findViewById(R.id.txttitle);
        viewholder.imgdelete = (ImageButton) view.findViewById(R.id.imgdelete);


        viewholder.imgdelete.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                    list.remove(position);
                    notifyDataSetChanged();
            }
        });
        view.setTag(viewholder);
    }
    else
    {
        view  = convertView;
    }

    ViewHolder viewholder = (ViewHolder) view.getTag();
    viewholder.tvTitle.setText(list.get(position).getmTitle());

            return view;
}

Here is my Logcat error

     06-17 13:01:41.715: ERROR/AndroidRuntime(4284): FATAL EXCEPTION: main
06-17 13:01:41.715: ERROR/AndroidRuntime(4284): java.lang.IndexOutOfBoundsException: Invalid index 5, size is 5
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at java.util.ArrayList.remove(ArrayList.java:406)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at com.list.AdapterClass$1.onClick(AdapterClass.java:66)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at android.view.View.performClick(View.java:2408)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at android.view.View$PerformClick.run(View.java:8816)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at android.os.Handler.handleCallback(Handler.java:587)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at android.os.Handler.dispatchMessage(Handler.java:92)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at android.os.Looper.loop(Looper.java:123)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at android.app.ActivityThread.main(ActivityThread.java:4627)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at java.lang.reflect.Method.invokeNative(Native Method)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at java.lang.reflect.Method.invoke(Method.java:521)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
06-17 13:01:41.715: ERROR/AndroidRuntime(4284):     at dalvik.system.NativeStart.main(Native Method)
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242

7 Answers7

3

Try BaseAdapter instead of ArrayAdapter. Because BaseAdapter is best when you are working with custom views.

Here is sample code..

public class AdapterClass extends BaseAdapter{

        List<MyModelClass> list;
        Activity mActivity;

        public AdapterClass(Activity context,List<MyModelClass> objects)
        {
                this.list = objects;
                this.mActivity = context;
        }

        static class ViewHolder{
                protected TextView tvTitle;
                protected ImageButton imgdelete;
        }
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {


                final ViewHolder viewholder;
                if (convertView == null) 
                {
                        viewholder = new ViewHolder();
                        LayoutInflater inflator = mActivity.getLayoutInflater();
                        convertView = inflator.inflate(R.layout.mainn, null);
                        viewholder.tvTitle = (TextView) convertView.findViewById(R.id.txttitle);
                        viewholder.imgdelete = (ImageButton) convertView.findViewById(R.id.imgdelete);
                        convertView.setTag(viewholder);
                }
                else
                {
                    viewholder = (ViewHolder)convertView.getTag();
                }
                    viewholder.imgdelete.setOnClickListener(new OnClickListener() {

                            @Override
                            public void onClick(View v) {

                                    System.out.println("position - " + position + " size - "+ list.size());
                                    list.remove(position);
                                    notifyDataSetChanged();
                                    Toast.makeText(mActivity, "deleted", Toast.LENGTH_LONG).show();
                            }
                    });

                viewholder.tvTitle.setText(list.get(position).getmTitle());
                return convertView;
        }
        @Override
        public int getCount() {
            return list.size();
        }
        @Override
        public Object getItem(int position) {
            return position;
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
}
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
Niranj Patel
  • 32,980
  • 10
  • 97
  • 133
1

To delete the selected list...

1) remove notifyDataSetChanged();

2) put position itself argument to list.remove(position);

OR:

follow this steps:

1) take a Check box in list view. definitely you got list dynamically and show in adapter view.

2) in public View getView() holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                String updateall;
                DBConnect sts1 = new DBConnect(getApplicationContext(), "your database name");


                if(holder.checkBox.isChecked()){

                    updateall = "UPDATE Sever_Contain SET setcheck = 'true' WHERE id ="+cupos;
                    System.out.println(updateall);              

                }else{

                    updateall = "UPDATE Sever_Contain SET setcheck = 'false' WHERE id ="+cupos;
                    System.out.println(updateall);
                }
                    sts1.execNonQuery(updateall);                   
                    System.out.println(map);
                    sts1.close();
            }
        });

3) on delete click event just add: del.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            String deleteall = "DELETE from Sever_Contain where setcheck='true'";
            if(sts.isOpen()==false)
                sts.openDataBase();

                sts.execNonQuery(deleteall);                    
                sts.close();

        }
    });

4) from where do you start this Intent create onResume() method for update it.

This will help you.

Siten
  • 4,515
  • 9
  • 39
  • 64
0

u use the handler to update the listview

private Handler handler=new Handler()
{
        public void handleMessage(Message msg) {
        ArrayAdapter aa=new ArrayAdapter<String>(nextScreen.this,android.R.layout.test_list_item,mArray);
        list.setAdapter(aa);
        aa.notifyDataSetChanged();
        list.invalidate();              
}

};

if u want update the listview call the handler like this

handler.sendEmptyMessage(0);
kannappan
  • 2,250
  • 3
  • 25
  • 35
0

Use the concept of Handler here. Step1 Declare a constant private static final byte UPDATE_LIST = 100;

Step2 Call the handler onclick of button

viewholder.imgdelete.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                    Message msg = new Message();
                msg.what = UPDATE_LIST;
                msg.arg1 = position
                updateListHandler.sendMessage(msg);
            }
        });

Step3 Define the handler

private Handler updateListHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case UPDATE_LIST:
            int position = msg.arg1;
                list.remove(position);
                arrayAdapter.notifyDataSetChanged();
                break;

            }
            ;
        };
    };

See my response in How to divide and load a ListView in multiple parts?

Thanks Deepak

Community
  • 1
  • 1
Sunil Kumar Sahoo
  • 53,011
  • 55
  • 178
  • 243
0

I have been through the same problem few days back and asked the same question. Here is the link to that question. It will definitely help you.

Community
  • 1
  • 1
Varundroid
  • 9,135
  • 14
  • 63
  • 93
0

What i do when i need to delete an element from a listview is: in the onclick of the listview just remove the item from the string array (using which I populate the listview) and then call something like this:

listview.setAdapter(new ArrayAdapter<String>(this,R.layout.listviewactivity ,your_string_array));

works like a charm and no need to handle any index out of bound excpetion... hope it helps :)

Nitin
  • 1,451
  • 13
  • 17
0

Try:

 viewholder.imgdelete.setTag(position);
    viewholder.imgdelete.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

                list.remove((Integer)v.getTag());
                notifyDataSetChanged();
        }
    });

You should remove the final keyword from position parameter.

Ungureanu Liviu
  • 4,034
  • 4
  • 37
  • 42
  • hope that your "list" variable is a Arraylist or other List structure. In my example if you move viewholder.imgdelete.setTag(position); above viewholder.tvTitle.setText(list.get(position).getmTitle()); it will work :) – Ungureanu Liviu Jun 17 '11 at 20:14
  • I tried but didnt worked, so if you want I can provide you my full source. – Lalit Poptani Jun 18 '11 at 04:42