2016-08-25 91 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