Android Studio中Activity向类传值方法及RecyclerView删除按钮传参崩溃问题排查
二、RecyclerView删除按钮传参崩溃问题的解决方案
先给你拆解崩溃的核心原因,再一步步修复:
崩溃原因分析
从LogCat的报错信息来看,问题集中在三个点:
- Context为空:你的
CustomerDB实例初始化时没有传入有效的Context,导致调用getWritableDatabase()时触发NullPointerException。 - SQL语句写法错误:你错误地把
ContentValues直接拼到SQL条件里,完全不符合SQLiteDatabase.delete()的用法,会导致语法错误。 - ID传递逻辑有坑:用
GlobalVars.id存储当前项的ID,会因为RecyclerView的ViewHolder复用机制,导致点击删除时拿到的是最后一个可见项的ID,不是你实际点击的那个!
分步修复方法
1. 修复Context为空的问题
首先确保CustomerDB能拿到有效的Context:
- 先检查
CustomerDB的构造方法,必须接收Context参数:public class CustomerDB extends SQLiteOpenHelper { private static final String DATABASE_NAME = "your_db_name.db"; private static final int DATABASE_VERSION = 1; public CustomerDB(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } // ...其他数据库操作方法 } - 在RecyclerView Adapter的构造方法里传入Context,初始化
CustomerDB:public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.MyHolder> { private Context mContext; private CustomerDB mDb; // 你的数据集合:id, name等 public CustomerAdapter(Context context, List<Integer> idList, List<String> nameList, ...) { this.mContext = context; this.id = idList; this.name = nameList; // ...初始化其他数据集合 mDb = new CustomerDB(mContext); // 用传入的Context初始化数据库实例 } // ...其他Adapter方法 } - 在创建Adapter的Activity/Fragment里,传入当前的Context:
CustomerAdapter adapter = new CustomerAdapter(this, idList, nameList, ...);
2. 修复SQL删除语句的错误
SQLiteDatabase.delete()的正确用法是delete(表名, where条件, 条件参数数组),而且你之前拼写错了getWritableDatabase(原代码写的getWriteableDatabase是拼写错误),修改deleteCustomer方法:
public long deleteCustomer(String id) { SQLiteDatabase db = this.getWritableDatabase(); // 注意拼写正确! // 用占位符?来传递参数,避免SQL注入,也不会出现语法错误 return db.delete(TABLE_NAME, "Customer_ID = ?", new String[]{id}); }
3. 修复ID传递的逻辑缺陷
扔掉GlobalVars.id,直接在点击事件里获取当前点击项的ID:
修改onBindViewHolder方法:
public void onBindViewHolder(@NonNull MyHolder holder, final int position) { final String currentCustomerId = String.valueOf(id.get(position)); holder.idText.setText(currentCustomerId); holder.nameText.setText(String.valueOf(name.get(position))); // ...其他TextView的赋值逻辑 holder.delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 直接用当前position对应的ID,不会被ViewHolder复用影响 mDb.deleteCustomer(currentCustomerId); // 别忘了删除数据后更新数据源并刷新RecyclerView id.remove(position); name.remove(position); // ...移除其他对应数据集合的元素 notifyItemRemoved(position); notifyItemRangeChanged(position, getItemCount()); } }); }
额外优化提示
- 尽量不要在Adapter里直接操作数据库,建议把数据库逻辑放到专门的Repository类里,代码更清晰,也方便测试。
- 数据库操作属于耗时操作,最好放到子线程里执行,比如用Kotlin Coroutines或者Java的AsyncTask,避免阻塞主线程导致ANR。
内容的提问来源于stack exchange,提问作者adrian38
相关产品推荐
相关产品推荐

