Kotlin实现Android SQLite数据保存闪退排查及API31咨询
崩溃根因
从Logcat捕获的报错日志可以直接定位问题,和数据库操作逻辑本身没有直接关系:
Caused by: java.lang.NullPointerException: findViewById(R.id.buttonsave) must not be null
你在MainActivity的onCreate生命周期方法中,代码执行顺序完全错误:在调用setContentView(R.layout.activity_main)加载布局文件之前,就提前执行了buttonsave.setOnClickListener的控件绑定逻辑。此时布局还未挂载到Activity上,系统找不到对应ID的控件,直接触发空指针闪退。
额外注意:从你的菜单跳转逻辑看,点击新建笔记会跳转到addnoteactivity,如果buttonsave、editTextTitle、editTextdesc这三个控件是写在addnoteactivity对应的布局文件里,你把这部分保存逻辑写在MainActivity中,就算调整了顺序也会找不到控件报空指针,这部分逻辑需要写在addnoteactivity的代码中。
修复方案
1. 调整Activity代码执行顺序
所有控件查找、事件绑定、RecyclerView初始化逻辑,必须放在setContentView()调用之后执行。如果保存逻辑属于新建笔记页面,就把对应代码移到addnoteactivity中。
修正后的MainActivity onCreate示例:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 必须第一时间加载布局,之后再操作控件 setContentView(R.layout.activity_main) // 注意:如果buttonsave不在activity_main布局里,下面这段点击事件要移到addnoteactivity里 buttonsave.setOnClickListener { val dbManger= DBmanager(this) val values = ContentValues() values.put("Title",editTextTitle.text.toString()) values.put("Desc",editTextdesc.text.toString()) val insertId= dbManger.Insert(values) if (insertId > 0 ){ Toast.makeText(this, "یــادادشــت جـــدیِـد ذخـیره شـــد!", Toast.LENGTH_SHORT).show() } else{ Toast.makeText(this, " خطــا در ذخـیره یــادادشــت !", Toast.LENGTH_SHORT).show() } } layoutManger = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) adapter = Adapter() val list = ArrayList<Model>() list.apply { add(Model("fatemeh", "chamani fard")) add(Model("reyhaneh", "chamani fard")) add(Model("bahareh", "chamani fard")) add(Model("abolfazl", "chamani fard")) } adapter.setList(list) list_main.layoutManager=layoutManger list_main.adapter=adapter }
2. 修复数据库类的潜在问题
你写的DBmanager类还有几个会触发异常的隐患,需要同步修改:
- 类定义开头多打了冗余字符
h,把hclass DBmanager改成class DBmanager - 建表语句的ID列添加自增属性,避免插入数据时不传ID导致报错,修改建表SQL为:
val sqlCreateTable="CREATE TABLE IF NOT EXISTS " + dbTable + " ("+ colID +" INTEGER PRIMARY KEY AUTOINCREMENT, "+ colTitle +" TEXT,"+ colDesc +" TEXT);"
- 删除
DatabaseHelper的onCreate方法里弹Toast的代码:SQLiteOpenHelper的生命周期方法默认在工作线程执行,直接弹Toast会触发线程异常,数据库创建成功不需要额外给用户弹提示。 - 类名、变量名建议遵循Kotlin驼峰命名规范,比如
DBmanager改成DBManager,避免拼写错误导致的引用问题。
Android API 31 说明
- API 31是Android系统的API级别编号,对应正式发布的Android 12版本,2021年10月由Google正式推送
- 如果应用将
targetSdkVersion设置为31,必须适配Android 12的系统行为变更要求,比如:所有带intent-filter的四大组件必须显式声明android:exported属性、申请精确闹钟权限、适配通知运行时权限等,否则应用在Android 12设备上会出现安装失败、运行崩溃的问题。
内容的提问来源于stack exchange,提问作者F.chamani
相关产品推荐
相关产品推荐

