Search code examples
androidlistviewcustom-adapter

Delete button in customAdapter always removes last element


I don't know why if I click on delete button that is contained in list row, always removes last item, The toast msg in onClick delete function (deleteTag) displays correct item to remove. Also the deleted rows is not permanent- if I rotate device the list is full again. I really dont know what i doing wrong.

tagList (activity)

public class tagList extends AppCompatActivity {

    MyCustomAdapter myCustomAdapter;
    ListView tagLv;    

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tag_list);

        //Generate list View from ArrayList
        displayListView();
    }


    private void displayListView() {

        //Array list of tags, Tag(id,name,checked)
        ArrayList<Tag> TagList = new ArrayList<Tag>();

        TagList.add(new Tag(1, "aaa", false));
        TagList.add(new Tag(2, "bbb", false));
        TagList.add(new Tag(3, "ccc", false));

        //my adapter for listview
        myCustomAdapter = new MyCustomAdapter(tagList.this,R.layout.activity_tag_list,TagList);

        tagLv = (ListView) findViewById(R.id.tagLv);
        tagLv.setAdapter(myCustomAdapter);

    }

    // onClick
    public void deleteTag(View view){

        Tag itemToRemove = (Tag) view.getTag(R.string.tagListTag); //tagListTag= 1

        myCustomAdapter.remove(itemToRemove);
        myCustomAdapter.notifyDataSetChanged();

        Toast.makeText(getApplicationContext(),"item removed: " +itemToRemove.getName(),Toast.LENGTH_SHORT).show();
    }
}

MyCustomAdapter

public class MyCustomAdapter extends ArrayAdapter<Tag>{

    private ArrayList<Tag> tagList;
    private LayoutInflater layoutInflater;
    private Context context;


    public MyCustomAdapter(Context context, int resource, List<Tag> objects) {
        super(context, resource, objects);

        this.layoutInflater = LayoutInflater.from(context);
        this.tagList = new ArrayList<Tag>();
        this.tagList.addAll(objects);
        this.context = context;
    }

    private class ViewHolder {
        TextView textName;
        CheckBox cbName;
        Button rmBtn;
    }

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

        ViewHolder holder = null;

        if (convertView == null) {

            convertView = layoutInflater.inflate(R.layout.row_tag_item, null);

            holder = new ViewHolder();
            holder.textName = (TextView) convertView.findViewById(R.id.textName);
            holder.cbName = (CheckBox) convertView.findViewById(R.id.cbName);
            holder.rmBtn = (Button) convertView.findViewById(R.id.removeTagBtn);

            convertView.setTag(holder);

        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        Tag myTag = tagList.get(position);

        holder.textName.setText(" #" +  myTag.getId());

        holder.cbName.setText(myTag.getName());
        holder.cbName.setChecked(myTag.getSelected());

        holder.rmBtn.setTag(R.string.id, myTag.getId()); // id for future delete from DB
        holder.rmBtn.setTag(R.string.tagListTag, myTag);

        return convertView;
    }
}

Solution

  • The problem is that you are not using same list in activity as well as adapter. If you rotate it activity will be created again and you will be again setting adapter with original list.

    Solution :

    public MyCustomAdapter(Context context, int resource, List<Tag> objects) {
            super(context, resource, objects);
    
            this.layoutInflater = LayoutInflater.from(context);
            this.tagList = objects
            this.context = context;
        }
    

    In activity :

     public class tagList extends AppCompatActivity {
    
        MyCustomAdapter myCustomAdapter;
        ListView tagLv;    
       //Array list of tags, Tag(id,name,checked)
        ArrayList<Tag> TagList = new ArrayList<Tag>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_tag_list);
    
            //Generate list View from ArrayList
            displayListView();
        }
    
    
        private void displayListView() {
            TagList.add(new Tag(1, "aaa", false));
            TagList.add(new Tag(2, "bbb", false));
            TagList.add(new Tag(3, "ccc", false));
    
            //my adapter for listview
            myCustomAdapter = new MyCustomAdapter(tagList.this,R.layout.activity_tag_list,TagList);
    
            tagLv = (ListView) findViewById(R.id.tagLv);
            tagLv.setAdapter(myCustomAdapter);
    
        }
    
        // onClick
        public void deleteTag(View view){
    
            Tag itemToRemove = (Tag) view.getTag(R.string.tagListTag); //tagListTag= 1
    
            TagList.remove(itemToRemove);
            myCustomAdapter.notifyDataSetChanged();
    
            Toast.makeText(getApplicationContext(),"item removed: " +itemToRemove.getName(),Toast.LENGTH_SHORT).show();
        }
    }
    

    This will solve all the problems.