Android Studio线程结束后从SQLite(Room)读取数据崩溃问题咨询
问题原因分析与解决方案
1. 核心崩溃问题:Room数据完整性校验失败
这个报错是Room的典型schema变更异常,原因是你修改了数据库表的字段结构、新增/删除表之后,没有同步升级Room的版本号,Room检测到本地已有数据库的schema和当前代码定义的schema不匹配,就会抛出这个异常。
解决步骤:
- 找到你的
DbRoomDatabase类,定位类上方的@Database注解,把注解里的version属性值加1,比如原来值为1就改为2 - 如果你是在开发阶段,不需要保留旧版本的测试数据,可以直接在Room初始化代码中添加
.fallbackToDestructiveMigration()配置,版本升级时会直接清空旧表重建,不需要编写迁移逻辑,示例如下:
// DbRoomDatabase初始化示例 public static synchronized DbRoomDatabase getDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), DbRoomDatabase.class, "你的数据库文件名") // 开发阶段可开启,线上版本需要保留用户数据时不要使用 .fallbackToDestructiveMigration() .build(); } return INSTANCE; }
- 如果应用已经对外发布过旧版本,需要保留用户本地数据,就要根据你做的schema变更编写对应的Migration迁移逻辑,处理新旧版本的数据迁移。
2. 窗口泄漏(WindowLeaked)问题
这个是前序崩溃导致的次生问题:你的SyncActivity在onCreate中弹出了加载Dialog,但是因为前面的Room异常导致Activity被系统销毁,Dialog没有提前关闭,就会抛出这个窗口泄漏的报错。
解决步骤:
在SyncActivity的onDestroy生命周期方法中添加Dialog关闭逻辑:
@Override protected void onDestroy() { super.onDestroy(); if (loadingDialog != null && loadingDialog.isShowing()) { loadingDialog.dismiss(); } }
3. 现有同步代码的逻辑缺陷
你现在用while(thread.isAlive()){}的空循环等待线程执行完成的写法,会直接阻塞主线程,这也是你之前用AsyncTask实现时应用反复重启的核心原因:主线程长时间阻塞会触发ANR(应用无响应),系统会主动杀死并重启你的应用。
另外你在子线程中直接调用Looper.prepare()弹出Toast的写法也不规范,Android要求Toast必须在主线程展示,建议通过Handler切换到主线程再弹提示。
优化建议:
把同步逻辑改为回调式实现,不要用空循环阻塞主线程:
// 新增同步回调接口 public interface SyncCallback { void onWebDataGetSuccess(JSONObject webData); void onWebDataGetFail(); void onDbDataGetSuccess(List<News> dbNews); }
在对应逻辑执行完成后调用回调方法触发后续操作即可。
内容的提问来源于stack exchange,提问作者Zyx
相关产品推荐
相关产品推荐

