Search code examples
javaandroidsqlitelistviewencapsulation

Android: delete from database using index from listview - Can't access array of id's that is created with the view but not the basis for the list


I have a simple list view where each item is a view that has a title, from an ArrayList of strings and button, so that each entry in the ArrayList creates a new list item.

I also have another ArrayList of corresponding primary keys, which I want to use to delete specific items from an SQLite database but which isn't used in the list view(I don't want to display the ID's, but the strings that poplulate the list might not necessarily be unique so I can't use them to delete).

I have a onClick listener and method in the getView method for the list view, so that when someone clicks the delete button, I know the position in the list that the button was pressed in, so hopefully, I can then call a delete method on the database using id[position], however, I think due to the list view itself being created after the activity it's inside of, it can't resolve the id array, so I can't call delete.

public class TodayListActivity extends AppCompatActivity {

   private  ArrayList<String> names = new ArrayList<>();

   FoodDB Db = null;
   int deleteId;


   public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_todaylist);
    ListView lv = (ListView) findViewById(R.id.today_meal_list);

    Bundle a = this.getIntent().getExtras();

    String[] id = a.getStringArray("idArray"); //used to delete
    String[] mealNames = a.getStringArray("mealNamesArray"); //displayed

    Collections.addAll(names, mealNames);

    //call the list adapter to create views based off the array list 'names'
    lv.setAdapter(new MyListAdapter(this, R.layout.list_item, names));
}

  protected class MyListAdapter extends ArrayAdapter<String> {
    private int layout;

    private MyListAdapter(Context context, int resource, List<String> objects) {
        super(context, resource, objects);
        layout = resource;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        viewHolder viewholder;
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(layout, parent, false);
            viewholder = new viewHolder();
            viewholder.title = (TextView) convertView.findViewById(R.id.report_meal_name);
            viewholder.delButton = (Button) convertView.findViewById(R.id.button_delete_meal);
            viewholder.delButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int position = (Integer)v.getTag();
                    //int deleteId derived from id[position]
                    deleteId = Integer.parseInt(id[position]);
                    idToDelete(deleteId);
                    //update the list view to exclude the deleted item
                    names.remove(position);
                    notifyDataSetChanged();
                }
            });

            convertView.setTag(viewholder);
        } else {
            viewholder = (viewHolder) convertView.getTag();
        }
        //set string value for title
        viewholder.title.setText(getItem(position));
        viewholder.delButton.setTag(position);
        return convertView;



    }
}
public class viewHolder {
    TextView title;
    TextView delButton;
}
//delete from database
public void idToDelete(int DeleteId){
    Db.deleteFoods(deleteId);
}

}

Any suggestions as to how or where to get either the position index out of the list view (to the activity, where the id array is) or get access to the id array inside the listview would be appreciated!


Solution

  • You can pass the id array to the MyListAdapter adapter, by changing this class' constructor to accept it as a parameter. Also, you are already passing the names list as a parameter, you should keep a reference to it so you can access it when the button is pressed.

    Here is an example:

    protected class MyListAdapter extends ArrayAdapter<String> {
        private int layout;
        private List<String> names;
        private String[] ids;
    
        private MyListAdapter(Context context, int resource, List<String> names, String[] ids) {
            super(context, resource, names);
            layout = resource;
            this.names = names;
            this.ids = ids;
        }
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ...
            viewholder.delButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int deleteId = Integer.parseInt(ids[position]);// the "position" variable needs to be set to "final" in order to access it in here.
                    idToDelete(deleteId);
                    names.remove(position);
                    notifyDataSetChanged();
                }
            });
            ....
        }
    }
    

    and here is how you can create an instance of this adapter:

    lv.setAdapter(new MyListAdapter(this, R.layout.list_item, names, id));