You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中Activity向类传值方法及RecyclerView删除按钮传参崩溃问题排查

二、RecyclerView删除按钮传参崩溃问题的解决方案

先给你拆解崩溃的核心原因,再一步步修复:

崩溃原因分析

从LogCat的报错信息来看,问题集中在三个点:

  1. Context为空:你的CustomerDB实例初始化时没有传入有效的Context,导致调用getWritableDatabase()时触发NullPointerException。
  2. SQL语句写法错误:你错误地把ContentValues直接拼到SQL条件里,完全不符合SQLiteDatabase.delete()的用法,会导致语法错误。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:32:34