【问题标题】:Deleted Content is Still Displayed in Log-cat,[ Android,Java]Log-cat中仍然显示删除的内容,[Android,Java]
【发布时间】:2018-02-01 00:27:28
【问题描述】:

我真的需要你的帮助。我正在使用回收视图,但此时我正在尝试调试我的代码并通过 LogCat 检查我可能的错误源。从代码中,每当我通过单击方法删除数据(学校班级)时,我都会显示 SQLite 数据库中的内容,以查看数据是否真正被删除。当我单击删除按钮删除特定数据(学校班级)时,它应该在 LogCat 中显示 SQLite 数据库中的所有内容,但已删除的特定内容除外。

但目前,数据库显示所有内容,包括预期删除的内容。可能是什么问题,内容实际上被删除了吗?我的整个代码可能有什么问题。我将非常感谢您的回答。谢谢!!

这里是带有 onclick 方法的 AdapterClass,用于 onclick 事件。注意removeAt(getLayoutPosition());

public class ClassListOnSetupRecyclerAdapter extends RecyclerView.Adapter<ClassListOnSetupRecyclerAdapter.ClassListViewOnSetupHolder>{
    //simple list of classes(mDataSet for Adapter)
    private List<ClassesBean> listClasses;
    private RecyclerView mRecyclerView;
    private Context mContext;

    public ClassListOnSetupRecyclerAdapter(List<ClassesBean> listClasses){

        this.listClasses = listClasses;
    }

    @Override
    public ClassListViewOnSetupHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_classesname_recycler,parent,false);
        return new ClassListViewOnSetupHolder(itemView);
    }

    @Override
    public void onBindViewHolder(ClassListViewOnSetupHolder holder, int position) {
        holder.textView_classname.setText(listClasses.get(position).getClasses_name());
    }

    @Override
    public int getItemCount() {
        Log.v(ClassListOnSetupRecyclerAdapter.class.getSimpleName(),""+listClasses.size());
        return listClasses.size();
    }

  //  The View Holder Class
    public class ClassListViewOnSetupHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView textView_classname;
        public Button delete_button_classsetup;
        public ClassListViewOnSetupHolder(View itemView) {
            super(itemView);
            textView_classname = itemView.findViewById(R.id.textView_classname);
            delete_button_classsetup = itemView.findViewById(R.id.delete_button_classsetup);
            itemView.setOnClickListener(this);
            delete_button_classsetup.setOnClickListener(this);
            textView_classname.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {

            Toast.makeText(view.getContext(), "position = " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
            Log.i("Removed", "pressed");
            if(view.equals(delete_button_classsetup)){                     
                removeAt(getLayoutPosition());                  
                Log.i("dbDel", "Successful");
            }
        }
    }

removeAt() 方法

public void removeAt(int position){              
            demeaSQL.deleteAClass(classesBean);

                listClasses.remove(position);
                mRecyclerView.removeViewAt(position);
                notifyItemRemoved(position);
                notifyItemRangeChanged(position, listClasses.size());
                notifyDataSetChanged();

            if (demeaSQL != null) {
                StringBuilder sb = new StringBuilder();
                for (ClassesBean c : demeaSQL.getAllClasses()) {
                    sb.append(" ClassName= " + c.getClasses_name() + " ClassItemIndex= " + c.getClasses_item_index());
                    sb.append("\n");
                }
                Log.i("dbContent", sb.toString());
            }    
        }

SQLDatabase 删除函数。

public void deleteAClass(ClassesBean aClass){
        SQLiteDatabase db =this.getWritableDatabase();    
        db.delete(TABLE_CLASSES,COLUMN_CLASSES_ID + "=?",
                new String[]{String.valueOf(aClass.getId())});  
        db.close();  
    }

创建 classes_table sql 查询

 private String CREATE_CLASSES_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_CLASSES + "("
            + COLUMN_CLASSES_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_CLASS_ITEM_INDEX + " NUMBER,"
            + COLUMN_CLASSES_NAME + " VARCHAR," + COLUMN_CLASSES_CODENAME + " VARCHAR, " + COLUMN_CLASSES_SECTIONS + " VARCHAR," + COLUMN_CLASSES_TEACHERS
            + " VARCHAR," + COLUMN_CLASSES_STUDENTS + " VARCHAR" + ")";
@Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

        sqLiteDatabase.execSQL(CREATE_USER_TABLE);
        sqLiteDatabase.execSQL(CREATE_SCHOOL_TABLE);
        sqLiteDatabase.execSQL(CREATE_CLASSES_TABLE);    
    }

这是我的 ClassesBean 类。

public class ClassesBean {    
    private int id;
    private int classes_item_index;
    private String classes_name;
    private String classes_codename;
    private String classes_sections;
    private String classes_teachers;
    private String classes_students;

    public int getClasses_item_index() {
        return classes_item_index;
    }

    public void setClasses_item_index(int classes_item_index) {
        this.classes_item_index = classes_item_index;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getClasses_name() {
        return classes_name;
    }

    public void setClasses_name(String classes_name) {
        this.classes_name = classes_name;
    }

    public String getClasses_codename() {
        return classes_codename;
    }

    public void setClasses_codename(String classes_codename) {
        this.classes_codename = classes_codename;
    }

    public String getClasses_sections() {
        return classes_sections;
    }

    public void setClasses_sections(String classes_sections) {
        this.classes_sections = classes_sections;
    }

    public String getClasses_teachers() {
        return classes_teachers;
    }

    public void setClasses_teachers(String classes_teachers) {
        this.classes_teachers = classes_teachers;
    }

    public String getClasses_students() {
        return classes_students;
    }

    public void setClasses_students(String classes_students) {
        this.classes_students = classes_students;
    }    
}

【问题讨论】:

  • 所以您的问题实际上是关于为什么 delete 似乎不起作用?
  • 尝试调试并查看deleteAClass 中发生了什么 - 它被调用了吗?它是在抛出异常吗?你需要交易吗?传入的值是否正确?
  • 尝试使用public void deleteAClass(ClassesBean aClass){ SQLiteDatabase db =this.getWritableDatabase(); String id = String.valueOf(aClass.getId()); Cursor debug = db.query(TABLE_CLASS,null,COLUMN_CLASSES_ID + "=?",id,null,null,null); if (debug.getCount() &lt; 1) { Log.d("DELETEACLASS","ID " + id + " not in table " + TABLE_CLASS + "!!!"); } debug.close(); db.delete(TABLE_CLASSES,COLUMN_CLASSES_ID + "=?", new String[]{String.valueOf(aClass.getId())}); db.close(); } 然后查看日志。
  • 上述(作为 deleteAClass 方法的临时替代)将检查该行是否存在,如果不存在则将消息写入日志。这很可能是问题的原因。
  • 是的@ScaryWombat 删除不起作用。在“removeAt”方法中调用 deleteAClass。至于调试,我正在通过 Logcat 检查我的内容,看看它是否真的在删除。

标签: java android sqlite


【解决方案1】:

我认为您的问题是您使用 position 作为 id。

Position等同于在该位置显示数据的基础表中行的 id

例如对于只有插入的表,并且 RecyclerView 中的数据根据​​ id 顺序显示然后(最接近的 sceanrio):-

位置 0id 将是 1没有 id 0,因为第一个 id 是 1(除非你强制 0)).

位置 1id 将是 2 等等......

如果 id 为 1 的行已从表中删除,则 在 Position 0id 将是 2 等(后续删除,特别是如果不是在最后会引入进一步的差异)。

您必须使用其他方法来确定要删除的行。

  • 您可以从提取的光标构建一个互补/平行长数组,其中元素/位置 0 等于第一个 id 等(如果使用适配器进行过滤/排序则不好)。

  • 您可以使用对象数组作为适配器的源,其中对象的成员是相应的 id,这可以从实例中提取,由 位置 确定.

  • 如果显示的数据将唯一标识该行,则该行可用作删除的选择/where 子句。

编辑 - 工作示例

这是一个基于您的代码的工作示例(注意使用 longClick 进行删除,而 click 仅发出仅显示行 ID)。

数据库助手(仅用于类):-

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "acedema";
    public static final int DBVERSION = 1;
    public static final String TB_CLASSES = "classes";
    public static final String COL_CLASS_ID = BaseColumns._ID;
    public static final String COL_CLASS_ITEM_INDEX = "class_item_index";
    public static final String COL_CLASS_NAME = "class_name";
    public static final String COL_CLASS_CODENAME = "class_codename";
    public static final String COL_CLASS_SECTIONS = "class_section";
    public static final String COL_CLASS_TEACHERS = "class_teachers";
    public static final String COL_CLASS_STUDENTS = "class_students";

    SQLiteDatabase mDB;


    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String crtsql = "CREATE TABLE IF NOT EXISTS " + TB_CLASSES +
                "(" +
                COL_CLASS_ID + " INTEGER PRIMARY KEY, " +
                COL_CLASS_ITEM_INDEX + " NUMBER, " +
                COL_CLASS_NAME + " TEXT, " +
                COL_CLASS_CODENAME + " TEXT, " +
                COL_CLASS_SECTIONS + " TEXT, " +
                COL_CLASS_TEACHERS + " TEXT, " +
                COL_CLASS_STUDENTS + " TEXT " +
                ")";
        db.execSQL(crtsql);


    }

    public long insertClass(int item_index, String classname, String classcode, String classsections, String classteachers, String classstudents) {
        ContentValues cv = new ContentValues();
        cv.put(COL_CLASS_ITEM_INDEX,item_index);
        cv.put(COL_CLASS_NAME,classname);
        cv.put(COL_CLASS_CODENAME,classcode);
        cv.put(COL_CLASS_SECTIONS,classsections);
        cv.put(COL_CLASS_TEACHERS,classteachers);
        cv.put(COL_CLASS_STUDENTS,classstudents);
        return mDB.insert(TB_CLASSES,null,cv);
    }

    public int deleteAClass(long id) {
        String whereclause = COL_CLASS_ID + "=?";
        String[] whereargs = new String[]{String.valueOf(id)};
        return mDB.delete(TB_CLASSES,whereclause,whereargs);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public List<ClassesBean> getClasses() {

        ArrayList<ClassesBean> rv = new ArrayList<ClassesBean>();
        Cursor csr = mDB.query(TB_CLASSES,null,null,null,null,null,null);
        while (csr.moveToNext()) {
            ClassesBean cb = new ClassesBean();
            cb.setId(csr.getLong(csr.getColumnIndex(COL_CLASS_ID)));
            cb.setClasses_item_index(csr.getInt(csr.getColumnIndex(COL_CLASS_ITEM_INDEX)));
            cb.setClasses_name(csr.getString(csr.getColumnIndex(COL_CLASS_NAME)));
            cb.setClasses_codename(csr.getString(csr.getColumnIndex(COL_CLASS_CODENAME)));
            cb.setClasses_sections(csr.getString(csr.getColumnIndex(COL_CLASS_SECTIONS)));
            cb.setClasses_teachers(csr.getString(csr.getColumnIndex(COL_CLASS_TEACHERS)));
            cb.setClasses_students(csr.getString(csr.getColumnIndex(COL_CLASS_STUDENTS)));
            rv.add(cb);
        }
        return rv;
    }
}

注意事项

  • getClasses 方法用于从表中获取类。
  • deleteAClass 是根据 id 删除一个类。

MainActivity.java

这是显示 RecyclerView 的 Activity:-

public class MainActivity extends AppCompatActivity {
    RecyclerView mClassListRV;
    ClassRVAdapter mCRVAdapter;
    LinearLayoutManager mLLM;
    DBHelper mDBH;
    List<ClassesBean> mClassList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mClassListRV = (RecyclerView) this.findViewById(R.id.classlist);
        mDBH = new DBHelper(this); // Ready to use DBHelper

        addSomeData(); //<<<< Add some data for testing

        mClassList = mDBH.getClasses(); // Get the list of classes from the DB

        mLLM = new LinearLayoutManager(this); 
        mClassListRV.setHasFixedSize(true);
        mClassListRV.setLayoutManager(mLLM);
        mCRVAdapter = new ClassRVAdapter(this,mClassList);
        mClassListRV.setAdapter(mCRVAdapter);
    }

    public void removeAt(int position, long id) {
        mDBH.deleteAClass(id);

        mClassList.remove(position);
        mClassListRV.removeViewAt(position);
        mCRVAdapter.notifyItemRemoved(position);
        mCRVAdapter.notifyDataSetChanged();
    }


    private void addSomeData() {
        if (DatabaseUtils.queryNumEntries(mDBH.getWritableDatabase(),DBHelper.TB_CLASSES) < 1) {
            mDBH.insertClass(10, "English", "E101", "XYZ", "Fred Smith, Bert Bloggs", "JANET, JOHN");
            mDBH.insertClass(11, "English Literature", "E201", "ZXY", "Tom Brown, Bill Rigidspear", "JOHN, MARY");
            mDBH.insertClass(22, "Chemistry", "C045", "H2O", "Bert Steinein", "SUSAN, JOE");
        }
    }
}

注意事项

  • addSomeData 方法只是添加一些数据进行测试,但前提是没有数据。
  • removeAt 方法是在长按项目时调用的方法。

ClassRVAdapter.java

这相当于ClassListOnSetupRecyclerAdapter,但简化为仅列出班级名称和教师列。

public class ClassRVAdapter extends RecyclerView.Adapter<ClassRVAdapter.ClassViewHolder> {

    private List<ClassesBean> mClasses;
    Context mContext;

    public static class ClassViewHolder extends RecyclerView.ViewHolder {

        TextView mClassName;
        TextView mTeachers;

        public ClassViewHolder(final Context context, View v, final List<ClassesBean> classes) {
            super(v);
            mClassName = (TextView) v.findViewById(R.id.classname);
            mTeachers = (TextView) v.findViewById(R.id.teachers);
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    long id = classes.get(getAdapterPosition()).getId();
                    Toast.makeText(context,"You Clicked ID = " + String.valueOf(id), Toast.LENGTH_SHORT).show();
                }
            });
            v.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    ((MainActivity) context).removeAt(getAdapterPosition(),classes.get(getAdapterPosition()).getId());
                    return true; // Mark event as having been handled
                }
            });
        }
    }

    public ClassRVAdapter(Context context, List<ClassesBean> classes) {
        mContext = context;
        mClasses = classes;
    }

    @Override
    public ClassRVAdapter.ClassViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.class_list_item, parent, false);
        return new ClassViewHolder(mContext,v,mClasses);
    }

    @Override
    public void onBindViewHolder(ClassViewHolder vh, int position) {
        vh.mClassName.setText(mClasses.get(position).getClasses_name());
        vh.mTeachers.setText(mClasses.get(position).getClasses_teachers());    
    }

    @Override
    public int getItemCount() {
        return mClasses.size();
    }
}

ClassesBean.java

public class ClassesBean {
    private long id;
    private int classes_item_index;
    private String classes_name;
    private String classes_codename;
    private String classes_sections;
    private String classes_teachers;
    private String classes_students;

    public int getClasses_item_index() {
        return classes_item_index;
    }

    public void setClasses_item_index(int classes_item_index) {
        this.classes_item_index = classes_item_index;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getClasses_name() {
        return classes_name;
    }

    public void setClasses_name(String classes_name) {
        this.classes_name = classes_name;
    }

    public String getClasses_codename() {
        return classes_codename;
    }

    public void setClasses_codename(String classes_codename) {
        this.classes_codename = classes_codename;
    }

    public String getClasses_sections() {
        return classes_sections;
    }

    public void setClasses_sections(String classes_sections) {
        this.classes_sections = classes_sections;
    }

    public String getClasses_teachers() {
        return classes_teachers;
    }

    public void setClasses_teachers(String classes_teachers) {
        this.classes_teachers = classes_teachers;
    }

    public String getClasses_students() {
        return classes_students;
    }

    public void setClasses_students(String classes_students) {
        this.classes_students = classes_students;
    }
}

注意事项

  • id 已从 int 更改为 long,否则保持不变。

class_list_item.xml

只是匆忙拼凑的布局:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp">
    <TextView
        android:id="@+id/classname"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent" />
    <TextView
        android:id="@+id/teachers"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent" />
</LinearLayout>

结果:-

初始显示:-

点击第二行(Toast):-

第二行长按(删除):-

【讨论】:

  • 你好@MikeT 我喜欢你的回答,我很理解这一点,但是数据库类中的删除方法怎么样。它至少应该在我可以将其应用到回收视图之前执行删除,然后我将关注位置和 ids 匹配。在此刻。我只是想通过 onclick 侦听器执行一个简单的删除操作,以检查我的删除功能的可行性。虽然我还没有尝试过你作为建议提供的代码。以上我会立即尝试,我开始工作并回复你。
  • @Aham_Uzoma 删除取决于单击,单击是列表中的一个项目,因此删除需要位置。您必须将某些内容传递给removeAt,以便它可以将某些内容传递给deleteAClass。我看不出classesBean 与职位的关系。 onClick 中的 Toast 给人的印象是您正在使用位置。请参阅我之前的评论并复制该代码作为deleteAClass 的替代品,如果 id 不是表中的一行,它将显示正在传递的 id。
  • 您好先生@MikeT 我已经运行了您提供的代码。而且 id 出现语法错误,它需要一个数组,所以我将其更改为 'String[] id = {String.valueOf(aClass.getId())};' .这是我在日志 D/DELETEACLASS 中得到的:ID [Ljava.lang.String;@d901fef 不在表类中!!!
  • 请@MikeT 这是什么意思,我该如何解决它。感谢您,这是我在过去一周中发现的最有意义的调试,试图解决这个问题。
  • [Ljava.lang.String;@d901fef 显然不是 id(整数)。而是 aCLass.getId() 返回一个字符串数组。见what is Ljava.lang.String;@。也许传递位置(removeAt(getAdapterPosition()); 并将其用作从aCalss.getId() 返回的字符串数组的索引可能是应该删除的 id。取决于 ClassesBean 类(可能编辑您的问题以包括 ClassesBean)
猜你喜欢
  • 2013-01-30
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多