2016-08-25 6 views
0

동일한 쿼리를 수행 할 때마다 영역 데이터가 때때로 다른 데이터를 반환하는 문제가 있습니다. 현재 업로드를 위해 SyncAdapter를 사용하고 있습니다. 아이디어는 우리가 오프라인 모드를 구현하려고한다는 것입니다.영역 데이터가 일치하지 않습니다

사용자가 항목을 만들면 사용자가 영역 DB에 추가됩니다. maxId를 가져 와서 1000을 추가하여 해당 항목의 ID를 수동으로 생성합니다. 그런 다음 itemID를 UploadSyncAdapter에 보내서 itemById를 가져 와서 백엔드로 보내면 백엔드에서 실제 ID가있는 항목을 반환합니다. 그래서 나는 이전 항목을 지우고 새 항목을 영역에 삽입합니다.

내가 돌아가서 데이터를 읽은 후 매번 두 번째 시간 (예 : 크기 115의 데이터 배열과 크기 116의 배열)을 반환합니다. ID로 디버거로 항목을 검색하고 실제로 한 번 두 번째로 찾지 않는 항목을 찾습니다. 하지만 프로젝트를 다시 작성한 후 항목이 있고 정상적으로 작동하거나 인스턴트 실행을 사용하여 앱을 다시 실행 한 것처럼 보입니다.

감사 어떤 도움 ...

UPDATE Btw은 내가 서버에서 데이터를 얻을 수 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

적절한 답을 제공하기 위해 새 요소를 삭제하고 삽입하는 거래 코드를 확인해야합니다. 내 생각 엔 당신이 배경 스레드에서 여러 트랜잭션을 사용하고 트랜잭션 내에서 요소를 얻기 위해 쿼리를 평가하지 않는 것입니다. 또한 작업을 마쳤 으면 백그라운드 스레드의 영역 (동기화 어댑터의 스레드)을 닫은 후 다음 작업을 위해 영역 인스턴스를 다시 엽니 다. – EpicPandaForce

+0

아, 나는 옳았다 : 여러 트랜잭션과 트랜잭션 외부에서 쓰기의 매개 변수를 결정하기위한 쿼리를 수행한다. ('filterTasksByPermission'에 대한 코드를 보는 것이 좋겠지 만) – EpicPandaForce

+0

또한'영역을 넣는 것을 고려해야한다. 'finally {'에서'close()'를 사용하십시오. – EpicPandaForce

답변

5

몇 가지 조사를 한 후에 문제가 무엇인지 알아 냈습니다. 하지만 내가 틀렸다면 나를 바로 잡아주세요. 내 Rx 호출에서 Subscribers.io()를 Subscribers.newThread()로 바꿨으므로 이제는 정상적으로 작동합니다. 그래서 내 이론은 :

변경된 데이터를 업로드하기 전에 UploadAdapter를 호출하기 전에 Subscribers.io()와 함께 Rx 호출을 사용하여 데이터베이스에 항목을 삽입하고 있습니다. Subscribers.io()는 스레드 풀을 사용하여 스레드를 재사용하거나 필요한 경우 새 스레드를 만듭니다. 그러면 "A"라는 스레드가 생성된다고 가정 해 봅시다. 스레드 A의 렘 인스턴스를 얻습니다 (렐름 스냅 샷이 "1"이라고 가정 해 봅시다). 생성 된 아이템을 삽입합니다. 그런 다음 SyncAdapter get이 호출되고 동일한 Realm 스냅 샷 "1"이있는 새 Realm 인스턴스가 생성됩니다. SyncAdapter가 서버에 데이터 업로드를 완료하면 이전 항목을 삭제하고 서버에서 가져온 새 항목을 삽입합니다. 따라서이 영역 데이터가 변경된 후에는 최신 영역 스냅 샷이 이제 "2"가됩니다. SyncAdapter는 업로드가 완료된 브로드 캐스트를 활동으로 보내고 영역 데이터베이스에서 새 데이터를 가져와야합니다.

영역에서 데이터를 읽으려면 Subscribers.io()에도 Rx를 사용하고 있습니다. 따라서 Realm에서 새 데이터를 요청할 때 Subscribers.io()는 이미 재사용 대기중인 풀을 가지고 있으며 스레드 "A"입니다. 이 스레드는 비 루퍼 스레드이므로 Realm 데이터가 변경되었음을 알지 못하며 영역 스냅 샷 "1"을 여전히 사용하므로 Realm에서 이전 데이터를 가져옵니다. Subscribers.io()가 새 스레드를 만들었을 때 스레드를 "B"라고 가정 해 봅니다.

그래서 스레드 "B"는 영역 스냅 샷을 가져오고 이번에는 최신 스냅 샷이므로 스냅 샷 "2"입니다. 그리고 올바른 데이터를 반환합니다.

따라서 Subscribers.newThread()를 사용하면 항상 새로운 스레드가 만들어지고 항상 최신 영역 스냅 샷이 생성됩니다.이 사람을 도움이 Retrofit with Rxjava Schedulers.newThread() vs Schedulers.io()

희망 :

여기 Subscribers.io()와 Subscribers.newThread()의 차이에 대한 링크입니다!

+0

좋은 찾으십시오. 그건 의미가 있습니다. – EpicPandaForce

관련 문제