androidlistviewandroid-sqliteandroid-arrayadaptercustom-arrayadapter

Delete corresponding Item from Database on click of 'delete' button in ListView from Custom ArrayAdapter in Fragment


I am creating a demo Android app which has a ListView displaying in a fragment. Each List item has a text and a delete button, and the items are stored in SQLite database. I am having trouble understanding how to delete the corresponding item from the database when the delete button is clicked. I searched for various ways online, and could not figure out how to get the _ID value (set to autoincrement) of the row item in the DB, so that the item could be deleted.

The custom Adapter class

public class CustomListAdapter extends ArrayAdapter<DataModel> implements View.OnClickListener{
private ArrayList<DataModel> dataSet;
Context mContext;
private TaskHelper_tab1 mHelper;

public CustomListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<DataModel> data) {
    super(context, resource, data);
    this.dataSet = data;
    this.mContext=context;
}

private static class ViewHolder {
    TextView txtName;
    Button btn;
}

@Override
public void onClick(View v) {
    int position=(Integer) v.getTag();
    Object object= getItem(position);
    DataModel dataModel=(DataModel)object;
    switch (v.getId())
    {
        case R.id.task_delete:
            Snackbar.make(v, "Release date " +dataModel.getName(), Snackbar.LENGTH_LONG)
                    .setAction("No action", null).show();
            break;
    }
}
private int lastPosition = -1;

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

    // Get the data item for this position
    final DataModel dataModel = getItem(position);

    // Check if an existing view is being reused, otherwise inflate the view
    final ViewHolder viewHolder; // view lookup cache stored in tag
    final View result;

    if (convertView == null) {

        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.task_list_long_term_item, parent, false);
        viewHolder.txtName = (TextView) convertView.findViewById(R.id.task_title);
        viewHolder.btn = (Button) convertView.findViewById(R.id.task_delete);
        result=convertView;
        convertView.setTag(viewHolder);
        viewHolder.btn.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {

                int id2 = (int) getItemId(position);

                Toast.makeText(mContext,id2 + " Button clicked" + position,Toast.LENGTH_SHORT).show();
                deleteTask(id2);
                notifyDataSetChanged();
            }
        });
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
        result=convertView;
    }
    lastPosition = position;
    viewHolder.txtName.setText(dataModel.getName());
    return convertView;
}

public void deleteTask(int position){
    mHelper = new TaskHelper_tab1(getContext());
    SQLiteDatabase db = mHelper.getWritableDatabase();
    db.execSQL("DELETE FROM " + Task_tab1.TaskEntry.TABLE + " WHERE " + Task_tab1.TaskEntry._ID + "= '" + position + "'");
    db.close();
}

}

The fragment code

public class fragment_tab1 extends Fragment{
//for db tasks
EditText editText = null;
private TaskHelper_tab1 mHelper;
FloatingActionButton fab_tab1;
private PopDialog.PopDialogListener listener; //listener to pass the text to parent activity
private TextView textViewDescr;
private CustomListAdapter mAdapter;

private View view;
private ListView list_calllog;
private ArrayList<DataModel> callLog;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mHelper = new TaskHelper_tab1(getContext());
    list_calllog = (ListView) getActivity().findViewById(R.id.list);
    updateUI(); //this works -- keep this to initially populate the UI on opening app
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    if(view==null)
    {
        view=inflater.inflate(R.layout.fragment_tab1, container,false);
    }
    else
    {
        ViewGroup parent = (ViewGroup) view.getParent();
        parent.removeView(view);
    }

    callLog= new ArrayList<>();
    callLog.add(new DataModel("Apple Pie", null)); //maybe add button here
    callLog.add(new DataModel("Banana Bread",null ));

    CustomListAdapter adapter=new CustomListAdapter(getActivity(),R.layout.task_list_long_term_item,callLog);
    list_calllog=(ListView)view.findViewById(R.id.list);
    list_calllog.setAdapter(adapter);

    fab_tab1 = (FloatingActionButton) view.findViewById(R.id.fab_tab1);
    fab_tab1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View tab1) {
            AlertDialog.Builder alert = new AlertDialog.Builder(getContext());

            LayoutInflater inflater = getActivity().getLayoutInflater();
            View view = inflater.inflate(R.layout.pop_dialog_layout, null);

            alert.setTitle("info")
                    .setMessage("dialog box message")
                    .setView(view)
                    .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {

                                    String edittext_descr = editText.getText().toString();
                                    applyTexts(edittext_descr);

                                    Toast toast = Toast.makeText(getContext(), "adadadaa", Toast.LENGTH_LONG);
                                    toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
                                    toast.show();
                                }
                            }
                    );
            alert.show();
            editText = view.findViewById(R.id.edit_text);
        }
    });
    return view;
}

@Override
public void applyTexts(String edittext_descr) {
    String task = String.valueOf(edittext_descr);
    SQLiteDatabase db = mHelper.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put(Task_tab1.TaskEntry.COL_TASK_TITLE, task);
    db.insertWithOnConflict(Task_tab1.TaskEntry.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
    db.close();
    updateUI();
}

private void updateUI() {
    ArrayList<DataModel> taskList = new ArrayList<>();
    SQLiteDatabase db = mHelper.getReadableDatabase();
    Cursor cursor = db.query(Task_tab1.TaskEntry.TABLE,
            new String[] {Task_tab1.TaskEntry._ID, Task_tab1.TaskEntry.COL_TASK_TITLE}, null, null, null, null, null);

    while(cursor.moveToNext()){
        int index = cursor.getColumnIndex(Task_tab1.TaskEntry.COL_TASK_TITLE);
        //add new task
        String str = cursor.getString(index);
        DataModel dm = new DataModel(str,null );
        taskList.add(dm);
    }

    if(mAdapter == null){
        mAdapter = new CustomListAdapter(getActivity(), R.layout.task_list_long_term_item, taskList );
        list_calllog.setAdapter(mAdapter);
    } else {
        mAdapter.clear();
        mAdapter.addAll(taskList);
        mAdapter.notifyDataSetChanged();
    }
    cursor.close();
    db.close();
}

}


Solution

  • I searched for various ways online, and could not figure out how to get the _ID value (set to autoincrement) of the row item in the DB, so that the item could be deleted.

    Aren't you querying the ID attribute for the object when you read the data from the database? If not, do that and store in the DataModel. Then when you get the object that was clicked, you have the ID:

    DataModel dataModel=(DataModel)object;
    
    // TODO: Use dataModel.getId()
    

    Hope that helps!