How to delete rows from recyclerView and sqlite database both?

蹲街弑〆低调 提交于 2019-12-19 10:15:50

问题


I'm creating an app with recycler view and SQLite database. When user enters some data, it is displayed in recycler view and also added to my database. Now I want to implement delete functionality in recycler view.

What I want:

I want to delete the required row from database and also from recycler view at the same time, without getting any unexpected results. And all the rows should be deleted.

What I've Tried:

I've implemented onLongClickListener on cardView of recycler view (I'm using cardView as the row of recycler view). now when use long clicks its, I'm getting adapter position. and delete the entry of database at that position.

But this gives me unexpected results like: All the rows deleted which are below the actual deleting row or the row which are deleted once appears back when the activity of recycler view is again created and never deleting last 2-3 rows, which database entries are deleted already.

My code of adapter of recycler view is:

public class AdapterForMain extends RecyclerView.Adapter<AdapterForMain.ViewHolder>{
ArrayList<String> mDataset;
ArrayList<String> mfooterSet;

private int[] icon;
MainActivity context;
DatabaseHelper myDb;


public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    // each data item is just a string in this case

    public TextView txtHeader;
    public TextView txtFooter;
    public ImageView imgView;
 //   MainActivity mainActivity;

    CardView cardView;

    public ViewHolder(View v) {
        super(v);
        txtHeader = (TextView) v.findViewById(R.id.firstLine);
        txtFooter = (TextView) v.findViewById(R.id.secondLine);
        imgView = (ImageView) v.findViewById(R.id.icon);

        cardView = (CardView)v.findViewById(R.id.cardView);
        cardView.setOnClickListener(this);
        cardView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                myDb = new DatabaseHelper(context);

                int detingPos = getAdapterPosition();
                boolean isDeleted = myDb.deleteEntry(detingPos);

                if(isDeleted){
                    mDataset.remove(getAdapterPosition());
                    notifyItemRemoved(getAdapterPosition());
                    notifyItemRangeChanged(getAdapterPosition(),mDataset.size());

                }
                Toast.makeText(context,"Delete from here",Toast.LENGTH_SHORT).show();

                  return true;
            }
        });
    }

    @Override
    public void onClick(View view) {

       // Toast.makeText(context,Integer.toString(getAdapterPosition()),Toast.LENGTH_SHORT).show();
        context.detailActivity(getAdapterPosition(),mDataset.get(getAdapterPosition()),mfooterSet.get(getAdapterPosition()));
    }
}


// Provide a suitable constructor (depends on the kind of dataset)
public AdapterForMain(ArrayList<String> myDataset, ArrayList<String> myFooterSet, int[] images, MainActivity context0) {
    icon = images;
    mDataset = myDataset;
    mfooterSet = myFooterSet;
    context = context0;
}

// Create new views (invoked by the layout manager)
@Override
public AdapterForMain.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
    // create a new view
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_main, parent, false);
    // set the view's size, margins, paddings and layout parameters
    ViewHolder vh = new ViewHolder(v);

    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element
    final String name = mDataset.get(position);
    holder.txtHeader.setText(mDataset.get(position));
    holder.txtHeader.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            //  Toast.makeText(AdapterForMain.this,"Settings Activity is under Construction.",Toast.LENGTH_SHORT).show();
        }
    });

    holder.txtFooter.setText(mfooterSet.get(position));
    holder.imgView.setImageResource(icon[position%1]);
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.size();
}}

And code of delete method:

    public boolean deleteEntry(int row) {
        SQLiteDatabase db=this.getWritableDatabase();
        db.delete(TABLE_NAME, COL_1 + "=" + row,null);
        return true;
    }

I've seen the following link for the solution but can't get exact solution for what I want.

Link 1
Link 2


回答1:


First of all you need to pass long to your delete method and not int. Secondly, your should pass the exact rowId to your method and not the adapter position. Because adapter position will always be continuous set of numbers from 0 to some number without gaps between, while in your database you will have some numbers not used for rowId after deletion of data from table. For example, if you delete the 5th row then index 4 is not used any more by SQLite db. Your will have rows like 0, 1, 2, 3, 5, 6... Because it is autoincrement.

I will advice you to store your data in two dimensional array or ArrayList. Then you need to pass values of COL_1 too with the corresponding text when retreiving data from db. That way you will be always aware of which row number contains particular data and show that row number when you want to delete it.

Because you have only one column for data, it will be easy to show you the version with two dimensional array.

You can imagine it as array of arrays:

mDataset ->

at positions:
0 | array1
1 | arrays2
2 | array3

... | ...

array1 ->

at positions:
0 | rowId
1 | textData

array2 ->

at positions:
0 | rowId
1 | textData

and so on. But you will need to change the code of method for retreiving data from db so that it will return the above mentioned ArrayList.

The code will look like below:

In your DataBase:

// getData method
public ArrayList<ArrayList<String>> getData() {
    SQLiteDatabase db=this.getWritableDatabase();
    String[] columns = new String[]{COL_1, COL_2};
    Cursor c = ourDatabase.query(TABLE_NAME, columns, null, null, null, null, null);

    int rowId = c.getColumnIndex(COL_1);
    int text = c.getColumnIndex(COL_2);

    ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();

    for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
        ArrayList<String> temp = new ArrayList<String>();
        temp.add(c.getString(rowId));
        temp.add(c.getString(text));
        data.add(temp);
    }

    return data;
}

// deleteEntry method
public boolean deleteEntry(long row) {
    SQLiteDatabase db=this.getWritableDatabase();
    db.delete(TABLE_NAME, COL_1 + "=" + row, null);
    return true;
}

DataSet:

ArrayList<ArrayList<String>> mDataSet = //initialize or pass data

then use it as:

int position = mDataset.get(getAdapterPosition).get(0);
boolean isDeleted = myDb.deleteEntry(Long.parseLong(position));

or

long position = mDataset.get(getAdapterPosition).get(0);
boolean isDeleted = myDb.deleteEntry(position);



回答2:


Deleting the object from Sqlite by its row id

// Deleting single contact  
    public void deleteContact(Contact contact) {  
        SQLiteDatabase db = this.getWritableDatabase();  
        db.delete(TABLE_CONTACTS, KEY_ID + " = ?",  
                new String[] { String.valueOf(contact.getID()) });  
        db.close();  
    } 
Deleting object from RecyclerView:

RecyclerView recyclerView= (RecyclerView) view.findViewById(R.id.recyclerView);

    LinearLayoutManager layoutManager=new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false);
    recyclerView.setLayoutManager(layoutManager);
    parseArgument();

    adapter=new ReviewRecyclerAdapter(reviewArrayList);
    recyclerView.setAdapter(adapter);
    recyclerView.setHasFixedSize(false);
    reviewArrayList.remove(contact);//pass contact you want to delete
    adapter.notifyDataSetChanged();


来源:https://stackoverflow.com/questions/39868291/how-to-delete-rows-from-recyclerview-and-sqlite-database-both

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!