2016-08-25 93 views
0

我有一个问题,即每次境界我做同样的查询时间有时会返回我不同的数据。目前我正在使用SyncAdapter进行上传。这个想法是我们正试图实现离线模式。领域的数据同步不一致

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

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

赞赏任何帮助...

UPDATE 顺便说一句,我使用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中)

+0

我需要查看您的交易代码,您在哪里删除并插入新元素以给出正确的答案。我的猜测是你在后台线程上使用多个事务,而不是评估查询来获取事务内的元素。此外,请确保在完成操作后关闭后台线程上的领域(以便同步适配器的线程),然后重新打开Realm实例以进行下一步操作。 – EpicPandaForce

+0

噢,看,我是对的:多个事务并执行查询来确定事务外的写入参数(虽然很高兴看到'filterTasksByPermission'的代码) – EpicPandaForce

+0

还应该考虑放置'realm。 close()'在'finally {'中。 – EpicPandaForce

回答

5

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

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

对于来自领域我也是用的Rx与Subscribers.io读取数据()。因此,当从Realm请求新数据时,Subscribers.io()在其池中已经有一个线程正在等待被重用,并且线程为“A”。由于此线程是非Looper线程,它不知道Realm数据已更改,它仍使用Realm快照“1”,所以这就是为什么我从Realm获取旧数据的原因。在刷新几次后,Subscribers.io()可能会创建一个新线程,比如线程“B”。

所以线程“B”也得到是一种境界snaphot,这一次,它是最新的快照,所以快照“2”。它会返回正确的数据。

因此,使用Subscribers.newThread()时,它总是创建一个新线程,它总是有最新的境界快照。

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

希望这可以帮助别人!

+0

很好找。这就说得通了。 – EpicPandaForce