领域数据同步不一致 [英] Realm data sync not consistent

查看:186
本文介绍了领域数据同步不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am having an issue where Realm sometimes returns me different data every time I do the same query. Currently I am using an SyncAdapter for uploading. The idea is that we are trying to implement offline mode.

所以当用户创建一个项目时,它的get被添加到Realm db。我通过获取maxId和添加1000手动生成该项目的ID。之后,我将itemID发送到UploadSyncAdapter,其中我获得itemById,并将其发送到后端,后端返回我的项目与真实的ID。

So when the User creates an item it get's added to Realm db. I am generating the ID for that item manually by getting the maxId and adding 1000 to it. After that I am sending the itemID to the UploadSyncAdapter where I get the itemById and send it to the backend and the backend returns me the item with the real ID. So after that I delete the old item and just insert the new item into Realm.

在我回去读取数据后,它每秒返回一个数组,例如一个数组大小为115的数据,另一个时间的数组大小为116.我甚至搜索项目与调试器的ID,它真的一次找到的项目,第二次它不。但它看起来像我重建项目后项目是在那里,它的工作正常,或者如果我通过使用即时运行重新运行应用程序。

After I go back and read the data it returns every second time for example an array of size 115 data and the other time an array of size 116. I even search for the item with the debugger by ID and it really once finds the item, the second time it doesn't. But it looks like after I rebuild the project the item is there and it works normally, or if I rerun the app by using Instant Run.

任何帮助赞赏...

UPDATE
Btw我使用RXjava从服务器获取数据,但它正在订阅并在当前线程(SyncAdapter thread)。

UPDATE Btw I am using RXjava to get the data from the server but it is being subscribed and observed on the current thread (SyncAdapter thread).

代码如下:

@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中,我也只是计算对象的2个字段,然后保存到Realm(所以我有那些值也保存在Realm中)

In the filterTasksByPermission I just calculate some permissions for the tasks, but the task is being returned in the list. And in the initializeTaskCustomFields I am also just calculating 2 fields of the object before saving to Realm (so that I have those values also saved in Realm)

推荐答案

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

After some researching I found out what was the problem. But please correct me if I'm wrong. I replaced my Subscribers.io() with Subscribers.newThread() in my Rx calls and now it works fine. So my theory is:

在调用我的UploadAdapter上传更改的数据之前,我使用与Subscribers.io()的Rx调用将我的项目插入数据库。 Subscribers.io()使用线程池来重用线程,或者如果需要创建新的线程。所以,让我们说它产生一个名为A的线程。线程A get是一个Realm实例(假设Realm快照为1),并将创建的项目插入其中。之后,SyncAdapter get被调用,它也得到一个具有相同Realm快照1的新Realm实例。 SyncAdapter完成将数据上传到服务器后,它会删除旧项目,并插入从服务器获得的新项目。因此,在这个领域数据更改后,最新的领域快照现在是2。 SyncAdapter向Activity发送一个广播,上传完成,它应该从Realm数据库中获取新数据。

Before calling my UploadAdapter to upload the changed data I am using an Rx call with Subscribers.io() to insert my item in the database. Subscribers.io() uses a threadpool to reuse threads, or creates new threads if neccessary. So let's say it spawns a thread called "A". Thread A get's a Realm instance (let's say that Realm snapshot is "1") and inserts into it the created item. After that SyncAdapter get's called and it also get's a new Realm instance with the same Realm snapshot "1". After SyncAdapter finishes uploading data to the server it deletes the old item, and insert the new item it got from the server. So after this Realm data changed so the newest Realm snapshot is now "2". SyncAdapter sends a broadcast to the Activity that the upload is finished and it should get the new data from the Realm database.

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

For reading data from Realm I am also using Rx with Subscribers.io(). So when requesting new data from Realm the Subscribers.io() has already a thread in it's pool that is waiting to be reused, and that's thread "A". And since this thread is a non Looper thread it doesn't know that Realm data changed and it still uses the Realm snapshot "1", so that's why I get old data from Realm. And after refreshing a few times Subscribers.io() probably creates a new thread, let's say thread "B".

所以线程B也得到了一个Realm snaphot,这次是最新的快照,所以快照为2。

So thread "B" also get's a Realm snaphot, and this time it is the newest snapshot, so snapshot "2". And it returns the correct data.

所以当使用Subscribers.newThread()它总是创建一个新的线程,它总是有最新的领域快照。

So when using Subscribers.newThread() it always creates a new thread and it always has the newest Realm snapshot.

这里是一个关于Subscribers.io()和Subscribers.newThread()之间的区别的链接:
使用Rxjava Schedulers.newThread()和Schedulers.io()进行改造

Here is a link regarding the difference between Subscribers.io() and Subscribers.newThread(): Retrofit with Rxjava Schedulers.newThread() vs Schedulers.io()

希望这有助于某人!

这篇关于领域数据同步不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆