我正在使用Recycler视图和SQLite数据库创建一个应用程序。当用户输入一些数据时,它将显示在回收站视图中,并且还会添加到我的数据库中。现在我想在recycler视图中实现delete
功能。
我想要的是什么:
我想从数据库中删除所需的行,同时也从Recycler视图中删除所需的行,而不会产生任何意外结果。并且应删除所有行。
我尝试过的事情:
我在回收站视图的
onLongClickListener
上实现了cardView
(我使用cardView作为回收站视图的行)。现在当使用长按它时,我正在获得适配器位置。并删除该位置的数据库条目。
但是这给了我意想不到的结果,例如:当再次创建Recycler视图的活动并且从不删除最后2-3行时,所有删除的实际删除行或删除的行之后的所有行都会显示回来数据库条目已被删除。
我的回收商视图适配器代码是:
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();
}}
delete
方法的代码:
public boolean deleteEntry(int row) {
SQLiteDatabase db=this.getWritableDatabase();
db.delete(TABLE_NAME, COL_1 + "=" + row,null);
return true;
}
我已经看到了解决方案的以下链接,但无法获得我想要的确切解决方案。
答案 0 :(得分:3)
首先,您需要将long
传递给删除方法,不 int
。其次,您应该将 exact rowId 传递给您的方法,并将不传递给适配器位置。因为适配器位置将始终是从0到某个数字的连续数字集之间没有间隙,而在数据库中,从表中删除数据后,将有一些数字不用于rowId。例如,如果删除第5行,则SQLite db不再使用索引4。你的行将有0,1,2,3,5,6 ......因为它是自动增量。
我建议您将数据存储在二维数组或ArrayList中。然后,当从db中检索数据时,您还需要使用相应文本传递COL_1
的值。这样,您将始终知道哪个行号包含特定数据,并在您要删除它时显示该行号。
因为您只有一列数据,所以很容易向您展示具有二维数组的版本。
您可以将其想象为数组数组:
mDataset - &gt;
位置:
0 |数组1
1 | arrays2
2 | ARRAY3 强>
...... | ...
array1 - &gt;
位置:
0 | ROWID
1 |的TextData 强>
array2 - &gt;
位置:
0 | ROWID
1 |的TextData 强>
等等。但是您需要更改从db中检索数据的方法代码,以便它返回上面提到的ArrayList。
代码如下所示:
在您的数据库中:
// 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;
}
数据集:
ArrayList<ArrayList<String>> mDataSet = //initialize or pass data
然后将其用作:
int position = mDataset.get(getAdapterPosition).get(0);
boolean isDeleted = myDb.deleteEntry(Long.parseLong(position));
或
long position = mDataset.get(getAdapterPosition).get(0);
boolean isDeleted = myDb.deleteEntry(position);
答案 1 :(得分:0)
通过行ID
从Sqlite中删除对象
// 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();