我正在创建一个带有回收器 View 和 SQLite 数据库的应用程序。当用户输入一些数据时,它会显示在回收器 View 中,并且也会添加到我的数据库中。现在我想在回收器 View 中实现删除
功能。
我想要什么:
我想同时从数据库和回收器 View 中删除所需的行,而不会得到任何意外的结果。并且所有行都应该被删除。
我尝试过的:
I've implemented
onLongClickListener
oncardView
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.
但这给了我意想不到的结果,例如:当再次创建回收器 View 的 Activity 时,实际删除行下方的所有已删除行或已删除的行都会出现,并且不会删除最后 2-3 行,这数据库条目已被删除。
我的回收器 View 适配器代码是:
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;
}
我已经看到了以下解决方案的链接,但无法获得我想要的确切解决方案。
最佳答案
首先,您需要将 long
传递给删除方法,而不是 int
。其次,您应该将准确的 rowId 传递给您的方法,而不是而不是适配器位置。因为适配器位置始终是从 0 到某个数字的连续数字集,之间没有间隙,而在数据库中,从表中删除数据后,您将有一些未用于 rowId 的数字。例如,如果删除第 5 行,则 SQLite 数据库将不再使用索引 4。您的行将有 0、1、2、3、5、6...之类的行,因为它是自动增量的。
我建议你将数据存储在二维数组或ArrayList中。然后,当从数据库检索数据时,您还需要传递 COL_1
的值以及相应的文本。这样,您将始终知道哪个行号包含特定数据,并在您想要删除它时显示该行号。
因为你只有一列数据,所以很容易向你展示二维数组的版本。
你可以把它想象成数组的数组:
mDataset ->
职位:
<强>0 |数组1
1 |数组2
2 |数组3
... | ...
数组1 ->
职位:
<强>0 | rowId
1 |文本数据
数组2 ->
职位:
<强>0 | rowId
1 |文本数据
等等。但是您需要更改从数据库检索数据的方法的代码,以便它将返回上面提到的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);
关于java - 如何从 recyclerView 和 sqlite 数据库中删除行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39868291/