【发布时间】:2020-01-22 12:12:56
【问题描述】:
背景:
我在我的 Android (Java) 项目中使用 Room 持久性库来支持数据的本地缓存。 Room 在查询或保存数据时在专用线程上运行。
问题:
如果在 Room 管理的这些线程之一中引发异常,则整个应用程序将崩溃。这可能发生在数据不一致的情况下,例如数据与当前架构不匹配。这是非常有问题的。我宁愿自己处理此类异常并擦除本地数据库中的所有数据 - 这比给用户留下一个完全损坏且无法修复的应用程序要好。
示例异常:
2020-01-22 12:45:08.252 9159-11043/com.xyz E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_1
Process: com.xyz, PID: 9159
java.lang.RuntimeException: Exception while computing database live data.
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "primary" (class com.xyz.model.remotedatasource.sampleApi.entities.ProfileImage), not marked as ignorable (2 known properties: "isPrimary", "url"])
at [Source: (byte[])":)
... -1, column: 402] (through reference chain: com.xyz.model.remotedatasource.sampleApi.entities.Candidate["profileImages"]->java.util.ArrayList[0]->com.xyz.model.remotedatasource.sampleApi.entities.ProfileImage["primary"])
at com.xyz.model.localdatasource.Converters.deserialize(Converters.java:113)
at com.xyz.model.localdatasource.Converters.toCandidate(Converters.java:73)
at com.xyz.model.localdatasource.LocalDao_Impl$4.call(LocalDao_Impl.java:270)
at com.xyz.model.localdatasource.LocalDao_Impl$4.call(LocalDao_Impl.java:217)
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
... 3 more
示例数据访问对象 (DAO):
public interface LocalDao {
@Query("SELECT * FROM Match")
LiveData<List<Match>> getMatches();
@Insert(onConflict = REPLACE)
void saveMatches(List<Match> matches);
}
问题
由于 Room 在后台线程中执行许多操作,我希望有一种方法可以注册自定义错误处理程序。你知道如何实现这一目标吗?如果没有,如果出现此类异常,您对如何自动擦除数据库有其他建议吗?
【问题讨论】:
-
我建议你提供一个 minimal reproducible example 来展示你的 DAO。或者,至少:你的 DAO 方法返回什么?我的猜测是他们正在返回
LiveData。 -
是的,他们正在返回 LiveData。我添加了 DAO 定义。
-
LiveData不能引发错误。这就是我不喜欢让 DAO 使用LiveData的原因之一。如果您切换到 RxJava 类型(例如,Single、Observable),您应该通过正常的 RxJava 链得到错误。或者,如果有一天你迁移到 Kotlin,你的异常应该通过正常的suspend和Flow处理暴露出来。
标签: java android android-room