Java 如何同时从recyclerView和sqlite数据库中删除行?

Java 如何同时从recyclerView和sqlite数据库中删除行?,java,android,database,sqlite,android-recyclerview,Java,Android,Database,Sqlite,Android Recyclerview,我正在使用recycler视图和SQLite数据库创建一个应用程序。当用户输入一些数据时,它将显示在回收器视图中,并添加到我的数据库中。现在我想在回收器视图中实现delete功能 我想要什么: 我想同时从数据库和recycler视图中删除所需的行,而不会得到任何意外的结果。并且应该删除所有行 我所尝试的: 我已经在回收器视图的cardwiew上实现了onLongClickListener(我使用cardwiew作为回收器视图的行)。现在,当使用长点击它,我得到适配器的位置。并删除该位置的数据库条

我正在使用recycler视图和SQLite数据库创建一个应用程序。当用户输入一些数据时,它将显示在回收器视图中,并添加到我的数据库中。现在我想在回收器视图中实现
delete
功能

我想要什么:

我想同时从数据库和recycler视图中删除所需的行,而不会得到任何意外的结果。并且应该删除所有行

我所尝试的:

我已经在回收器视图的
cardwiew
上实现了
onLongClickListener
(我使用cardwiew作为回收器视图的行)。现在,当使用长点击它,我得到适配器的位置。并删除该位置的数据库条目

但这会给我带来意想不到的结果,例如:当再次创建“回收器”视图的“活动”时,位于实际删除行下方的所有已删除行或已删除行会再次出现,并且不会删除最后2-3行,这些数据库条目已被删除

我的recycler视图适配器代码为:

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();
}}
我已经看到了解决方案的以下链接,但无法得到我想要的确切解决方案



首先,您需要将
long
传递给delete方法,而不传递
int
。其次,您应该将准确的rowId传递给您的方法,而传递适配器位置。因为适配器位置始终是从0到某个数字之间没有间隙的连续数字集,而在数据库中,从表中删除数据后,某些数字将不用于rowId。例如,如果删除第5行,则SQLite db不再使用索引4。您将有0、1、2、3、5、6等行。。。因为它是自动递增的

我建议您将数据存储在二维数组或ArrayList中。然后,在从数据库检索数据时,还需要将
COL_1
的值与相应的文本一起传递。这样,您将始终知道哪个行号包含特定数据,并在您要删除该行号时显示该行号

因为数据只有一列,所以很容易显示具有二维数组的版本

您可以将其想象为数组的数组:

mDataset->

位置:
0|array1
1|阵列2
2|阵列3

... | ...

阵列1->

位置:
0| rowId
1 |文本数据

阵列2->

位置:
0| rowId
1 |文本数据

等等。但您需要更改从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;
}

按行id从Sqlite中删除对象

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


删除后,您必须再次将适配器加载到RecycleServiceWuseadapter@pskink我不想使用自定义适配器,但如何重新加载?那么上面提到的其他一些意外结果呢?现在您正在使用一个自定义适配器,我发布的是一个通用的
游标
适配器。我知道我的逻辑中有什么问题。但是我的代码中的变化是:
int position=mDataset.get(getAdapterPosition.getRowId()
我无法理解
.getRowID()
部分。您可以通过使用通用的
光标
适配器,而不是使用
二维数组或ArrayList轻松地完成这项工作。
@pskink您很高兴,我们可以使用通用光标适配器轻松完成这项工作,但为此,我必须更改整个代码。首先,你在复制数据:这是存储所有数据的
光标
,那么在
数组列表
中复制它的原因是什么(我指的适配器只是使用该
光标
来提供数据),另外,您正在复制可能导致OOM错误的整个数据集(您在浪费内存和CPU时间),请注意,
SQLiteCursor
扩展了
AbstractWindowedCursor
,它将数据存储在一个小的
CursorWindow
中,从而允许处理甚至是巨大的数据集,第三,您已经注意到,内部的
ArrayList
只存储两个
String
s非常低效
// 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);
// 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:
    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();