Android Room删除任务时应用崩溃,报错主线程不可访问数据库
错误原因
- 崩溃直接原因是你在主线程执行了Room数据库操作,Room默认禁止主线程访问数据库,避免IO耗时阻塞UI导致ANR,这一点崩溃堆栈已经明确提示:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. - 另外你当前的删除逻辑调用的是
deleteAll(),会删除所有存储的任务,不符合你删除指定单个任务的需求。
修复步骤
1. 调整删除操作的执行线程
和你存储数据时的逻辑保持一致,把数据库删除操作放到子线程执行即可,你已经用过的AsyncTask.execute()可以直接复用。
2. 补充DAO层单条删除方法
在你的UserDao类中添加单条删除的注解方法:
@Dao public interface UserDao { // 你原有其他方法不变,新增下面的删除方法 @Delete void deleteSubtask(SubtaskDetails subtask); // 如果你暂时不想处理实体转换,也可以先按任务名查询删除(不推荐,重名会误删) @Query("DELETE FROM SubtaskDetails WHERE subtaskName = :name") void deleteByName(String name); }
3. 修改Adapter中的删除点击逻辑
把删除操作移到子线程,同时调整为删除当前选中的单条任务:
ivDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = (Integer) v.getTag(); subtask deletedTask = values.remove(position); remove(deletedTask); notifyDataSetChanged(); // 子线程执行数据库删除 AsyncTask.execute(() -> { // 方式1:如果你的subtask实体已经包含了数据库主键,直接转换为SubtaskDetails对象传入即可 AppDatabase.getDatabase(context).userDao().deleteSubtask(convertToDbEntity(deletedTask)); // 方式2:临时用名称删除(仅测试用) // AppDatabase.getDatabase(context).userDao().deleteByName(deletedTask.getSubtaskName()); }); } });
临时测试方案(禁止正式上线使用)
如果只是本地调试想快速验证功能,可以在初始化Room数据库时添加allowMainThreadQueries()配置,允许主线程操作数据库:
// 你的AppDatabase.getDatabase()方法内初始化的位置添加该配置 Room.databaseBuilder(context, AppDatabase.class, "your_db_name") .allowMainThreadQueries() // 仅本地测试使用,正式版务必移除 .build();
内容的提问来源于stack exchange,提问作者Aadhitya
相关产品推荐
相关产品推荐

