领域数据同步不一致

时间:2016-08-25 06:26:25

标签: android database synchronization realm

我遇到的问题是,每次我执行相同的查询时,Realm有时会返回不同的数据。目前我正在使用SyncAdapter进行上传。我们的想法是尝试实现离线模式。

因此,当用户创建项目时,它会被添加到Realm db中。我通过获取maxId并为其添加1000来手动生成该项目的ID。之后我将itemID发送到UploadSyncAdapter,在那里我获得itemById并将其发送到后端,后端返回带有真实ID的项目。所以在那之后我删除旧项目,然后将新项目插入Realm。

我回去读取数据后,它每秒都返回一次,例如一个115号数据的数组,另一个是116号数组。我甚至用ID搜索带有调试器的项目,它真的一次找到该项目,第二次没有。但是看起来在我重建项目之后项目就在那里并且它正常工作,或者如果我使用Instant Run重新运行应用程序。

任何帮助表示赞赏...

更新 顺便说一下,我使用RXjava从服务器获取数据,但它正在当前线程(SyncAdapter线程)上进行订阅和观察。

以下是代码:

@Override
public void onNext(TaskResponse taskResponse) {
     tasksDatabaseManager.deleteTaskById(taskId);
     List<Task> tasks = taskResponse.getTaskDataList();
     tasksDatabaseManager.insertTasks(tasks);
 }

public void deleteTaskById(int taskId){
    Realm realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    RealmResults<Task> rows = realm.where(Task.class).equalTo(ID, taskId).findAll();
    rows.deleteAllFromRealm();
    realm.commitTransaction();
    realm.close();
}

private void copyOrUpdateTasks(List<Task> tasksList){
    Realm realm = Realm.getDefaultInstance();
    ArrayList<Task> updatedTaskList;
    //first initialize task permissions
    updatedTaskList = filterTasksByPermission(tasksList);
    //initialize custom task data
    for (Task task : updatedTaskList) {
        initializeTaskCustomFields(task);
    }
    //save new data
    Log.d(TAG, "tasks number before update: " + getTasks().size());
    realm.beginTransaction();
    realm.copyToRealmOrUpdate(updatedTaskList);
    realm.commitTransaction();
    realm.close();

    Log.d(TAG, "tasks number after update: " + getTasks().size());
}

在filterTasksByPermission中,我只计算了一些任务的权限,但是在列表中返回了该任务。在initializeTaskCustomFields中,我也只是在保存到Realm之前计算对象的2个字段(这样我也将这些值保存在Realm中)

1 个答案:

答案 0 :(得分:7)

经过一番研究后,我发现了问题所在。但如果我错了,请纠正我。我在我的Rx调用中用Subscribers.newThread()替换了我的Subscribers.io(),现在它工作正常。所以我的理论是:

在调用我的UploadAdapter上传更改的数据之前,我正在使用与Subscribers.io()的Rx调用将我的项目插入数据库。 Subscribers.io()使用线程池重用线程,或者在必要时创建新线程。所以,让我们说它会产生一个名为&#34; A&#34;的线程。线程A得到一个Realm实例(让我们说Realm快照是&#34; 1&#34;)并在其中插入创建的项目。在调用SyncAdapter之后,它还会获得具有相同Realm快照的新Realm实例&#34; 1&#34;。 SyncAdapter完成将数据上传到服务器后,它会删除旧项目,并插入从服务器获取的新项目。因此,在Realm数据发生变化后,最新的Realm快照现在是#34; 2&#34;。 SyncAdapter向活动发送广播,说明上传已完成,它应该从Realm数据库中获取新数据。

为了从Realm读取数据,我也在使用Rx和Subscribers.io()。因此,当从Realm请求新数据时,Subscribers.io()已经有一个等待重用的池中的线程,以及该线程&#34; A&#34;。由于这个线程是一个非Looper线程,它不知道Realm数据已经改变,它仍然使用Realm快照&#34; 1&#34;,这就是我从Realm获取旧数据的原因。在刷新几次后,Subscribers.io()可能会创建一个新线程,让我们说线程&#34; B&#34;。

所以线程&#34; B&#34;这也是一个Realm snaphot,这次它是最新的快照,所以快照&#34; 2&#34;。它会返回正确的数据。

因此,当使用Subscribers.newThread()时,它总是创建一个新线程,并且它始终具有最新的Realm快照。

以下是有关Subscribers.io()和Subscribers.newThread()之间差异的链接: Retrofit with Rxjava Schedulers.newThread() vs Schedulers.io()

希望这有助于某人!