领域返回陈旧数据

时间:2017-01-29 19:11:44

标签: java android database realm kotlin

我没有很多编写Android应用的经验。为了好玩,我正在编写一个应用程序,将我的通话记录上传到我的服务器。整个应用程序作为服务运行。服务(在手机启动时启动)是注册ContentObserver的服务,然后调用我的自定义CallLog类。我使用ContentObserver来监听内容更改事件。不幸的是,当我例如,ContentObserver被多次调用。拨号。

出于这个原因,我在成功上传(我使用Retrofit)后调用了一个名为markAsUploaded()的函数。此函数会创建一个名为RealmObject的{​​{1}}(与我的常规CallLogUploaded模型不同)。这个CallLog只有一个标识符,它是调用的CallLogUploaded,应该足够独特。然后,当我遍历所有调用日志的列表时,我会针对dateTime函数检查每个调用日志,该函数执行Realm查询并检查是否已存储具有该dateTime的调用日志在数据库(领域)。从理论上讲,它应该有效。

但是,我注意到它并不总是有效。似乎我的数据经常是陈旧的。当我isDataUploaded()时,它返回false(虽然我发誓它返回true一次)。在我的realm.isAutoRefresh()函数中,即使我在Realm上执行isDataUploaded,我也看不到所有数据 - 但数据肯定会触及findAll()函数。

这是我的代码 - 它在Kotlin中,但应该很容易理解:

markDataAsUploaded

我是Realm的新手,也是Android开发的新手,所以我很感激你能给我的任何帮助。谢谢!

1 个答案:

答案 0 :(得分:1)

那是因为

// This function simply stores a Realm model for all the data that has been uploaded to the server
private fun markDataAsUploaded(dataToUpload: List<CallLog>) {
    realm = Realm.getDefaultInstance()
    for (data in dataToUpload) {
        realm.beginTransaction()
        val callLogUploaded = realm.createObject(CallLogUploaded::class.java)
        callLogUploaded.callDate = data.callDate

        realm.commitTransaction()
    }
}

此方法有quite a few errors that I had written about a long time ago

  • Realm实例已打开,但从未关闭

  • 每个元素都有一个新事务,而不是在一个事务中插入所有元素

如果您不关闭Realm实例(每个实例都需要自己的close()调用),那么您的Realm实例将永远不会更新,除非您实际开始事务并在事务中执行操作。

您有三种解决方案:

1。)在事务中的后台线程上执行你的逻辑,如果没有任何事情要做,那么取消事务 - 在事务中进行的查询永远不会陈旧

2。)确保Realm实例正确关闭(尽管这在任何非自动更新线程上都是必需的)

3.)hacky解决方案是致电RealmRefresh.refreshRealm() after getDefaultInstance() according to my answer on Stack Overflow which relies on package-private API, but it works to solve this issue

通常,您需要在线程的开头打开Realm实例,并在线程的末尾关闭它。

所以,try(Realm realm = Realm.getDefaultInstance() { ... }基本上只有一个onHandleIntent()

enqueue(new Callback() { @Override public void onSuccess(..) {...}在UI线程上运行。要在当前线程上运行它,您应该使用call.execute()

而不是

for (data in dataToUpload) {
    realm.beginTransaction()
    val callLogUploaded = realm.createObject(CallLogUploaded::class.java)
    callLogUploaded.callDate = data.callDate

    realm.commitTransaction()
}

DO

realm.beginTransaction()
for (data in dataToUpload) {
    val callLogUploaded = realm.createObject(CallLogUploaded::class.java)
    callLogUploaded.callDate = data.callDate
}
realm.commitTransaction()

要了解版本保留,您可以阅读https://medium.com/@Zhuinden/understanding-realm-version-retention-and-synchronization-9a513c2445bb