2017-05-13 5 views
0

GreenRobot을 사용하여 조각간에 RealmResults를 공유하려고합니다. 사용자가 I 표시 할 데이터를 변경 특정 버튼을 클릭하면, 나는 invalidateRealmResult 전화 :새 이벤트 버스 게시물에서 RealmResults가 삭제되지 않습니다.

public void invalidateRealmResult() { 
    RealmQuery<Climb> realmQuery = mRealm.where(Climb.class); 
    // other query modifiers added here.... 

    mResult = realmQuery.findAllSorted("date", Sort.ASCENDING); 
    RealmChangeListener listener = new RealmChangeListener<RealmResults<Climb>>() { 
      @Override 
     public void onChange(RealmResults<Climb> element) { 
      Log.d(TAG, "Realmresult onchange"); 
      EventBus.getDefault().postSticky(new RealmResultsEvent(mResult)); 
     } 
    }; 
    mResult.addChangeListener(listener); 
    EventBus.getDefault().postSticky(new RealmResultsEvent(mResult)); 
} 

내 greenrobot 이벤트는 다음과 같습니다

public class RealmResultsEvent { 
    public RealmResult mResult; 

    public RealmResultsEvent(RealmResult result){ 
     this.mResult = result 
    } 
} 

새로운 결과 구독 업데이트 할 필요가 모든 조각 이벤트에 : 나는 모든 조각 ONSTART (에 가입 할 것을 확인했다)와 중지시에서 탈퇴 한

@Subscribe(sticky = true) 
public void onRealmResultEvent(RealmResultsEvent event) { 
    mResult = event.mResult; 
    updateView(); 
} 

@Override 
public void onStop() { 
    super.onStop(); 
    EventBus.getDefault().unregister(this); 
} 

@Override 
public void onStart() { 
    super.onStart(); 
    EventBus.getDefault().register(this); 
} 

().

내 문제는 새 이벤트 게시물이 이전 RealmResults을 덮어 쓰지 않는 것으로 보입니다. 나는 RealmChangeListener에있는 로그 메시지가 영역 데이터베이스에 추가 될 때마다 증가하는 양을 얻게되고, UI는 잘못된 쿼리 결과를 보여주기 때문에 RealmResults이 파괴되지 않는다는 것을 알 수 있습니다.

05-13 10:36:55.523 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.536 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.544 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.551 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.558 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.566 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.574 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.583 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.591 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.600 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.608 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 
05-13 10:36:55.616 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange 

내가 변경할 때마다, 그 패턴을 반복, 교류 3, 6, 12, 6, 3, ... 배 리스너를 호출합니다. 이것이 의미하는 바가 무엇인지, 또는 그 정보가 누구에게 도움이되는지 확실하지 않습니다.

+0

안녕하세요 @ 그랜트카, 저는이 질문을 이해하고 있는지 잘 모르겠습니다. 'mResults'라는 두 개의 다른 변수가 있습니까? 내용을 변경하는 코드는 어디에 있습니까? 그러면 리스너가 실행됩니까? –

+0

안녕하세요 @ G.BlakeMeike, 네 거기에 내 MainActivity mResult 및 mResult 데이터를 표시하는 UI 요소가 들어 조각에 있습니다. 리스너를 실행하는 코드를 표시하지는 않았지만 기본적으로 클라이밍 객체를 영역에 추가하는 것입니다. – grantka

답변

0

문제를 좁힐 때까지 코드 조각을 제거 할 수있었습니다. 이벤트 버스와는 아무런 관련이 없습니다. 어떤 이유로 새로운 쿼리 결과에 realmresult를 재 할당 할 때 이전 realmresult를 가비지 수집하지 않으며 이전 결과에 대한 changelisteners가 여전히 실행 중입니다. 이로 인해 경합 조건이 만들어졌으며 마지막으로 완료 한 리스너가 내 UI에 표시됩니다.

나는 의사 현장 재 할당하기 전에 수신기를 제거하여이 고정 : 나는 의사 수정이 없기 때문에 전시 이상한 행동이 전화

public void invalidateRealmResult() { 
    RealmQuery<Climb> realmQuery = mRealm.where(Climb.class); 
    // other query modifiers added here.... 

    // ADDED THIS TO AVOID CALLING MULTIPLE LISTENERS 
    if(mResult != null) { 
     mResult.removeAllChangeListeners(); 
    } 
    mResult = realmQuery.findAllSorted("date", Sort.ASCENDING); 
    RealmChangeListener listener = new RealmChangeListener<RealmResults<Climb>>() { 
     @Override 
     public void onChange(RealmResults<Climb> element) { 
      Log.d(TAG, "Realmresult onchange"); 
      EventBus.getDefault().postSticky(new RealmResultsEvent(mResult)); 
     } 
    }; 
    mResult.addChangeListener(listener); 
    EventBus.getDefault().postSticky(new RealmResultsEvent(mResult)); 
} 

을하지만, 난 여전히 객체가 RealmResult하는 확신이 GC되지 않았고 이유가 확실하지 않습니다.

+0

GC를 사용하여 리스너를 제거하는 대신 RealmResults.removeChangeListener (listener)를 호출하는 것이 좋습니다. 알림 전달을 중지하십시오. – beeender

+0

@beeender 'mResult.removallAllChangeListeners()'는 무엇을합니까? 이 예제에서, 리스너를 제거하면 더 이상 로컬 변수'listener'에 액세스 할 수 없습니다. 필드 변수로 만들 수는 있지만 모든 담요를 제거 할 수있는 이유는 무엇입니까? – grantka

+0

어, 네,'mResult.removeAllChangeListeners()'가 그것을합니다. 핵심은'mResults'가 재 할당 된 직후 GC가 발생하지 않는다는 것입니다. – beeender

1

질문에 제공된 샘플 코드에서 invalidateRealmResult()이 호출 될 때마다 이전 mResult이 GC 화되지 않는 이유를 알기 어렵습니다. 청취자가 아직 응답하지 않기 때문에 귀하의 평가에 동의합니다. GC하지 않은 것으로 보입니다. 내 생각 엔 mResult에 대한 추가 참조가 있으므로 여기에 누락되었습니다.

일반 영역 용도 :

샘플을보고 한 번 관찰합니다. Climb 결과가 데이터베이스에 추가 될 때마다 쿼리를 다시 실행해야하는 이유는 확실하지 않습니다. 범위 results are live입니다. 즉, 쿼리 결과와 일치하는 기본 데이터가 변경되면 데이터가 자동으로 업데이트됩니다. 다시 쿼리 할 필요가 없습니다. 변경 리스너를 추가하면 해당 이벤트에 가입하여 결과 데이터가 변경되고 UI에 반응 할 수 있습니다. 당신은 다음과 같이 뭔가 코드를 조정하여,이 GC 문제를 일을 단순화하고 피할 수 있습니다 내가 단순의 GreenRobot 물건을했다,하지만 당신은 그것을 계속 사용할 수

@Override 
public void onStop() { 
    super.onStop(); 
} 

@Override 
public void onStart() { 
    super.onStart(); 
    mResult = fetchRealmResults() 
} 

public void fetchRealmResults() { 
    RealmQuery<Climb> realmQuery = mRealm.where(Climb.class); 
    // other query modifiers added here.... 

    // Async suffix is optional here, but will push 
    // the work to a worker thread and then come back 
    // with the results on the main thread. 
    mResult = realmQuery.findAllSortedAsync("date", Sort.ASCENDING); 
    RealmChangeListener listener = new 
    RealmChangeListener<RealmResults<Climb>>() { 
     @Override 
     public void onChange(RealmResults<Climb> element) { 
      // This will fire anytime there is a change 
      // to the underlying database that affects 
      // the results of this query. 
      Log.d(TAG, "Realmresult onchange"); 
      updateView(); 
     } 
    }; 
    mResult.addChangeListener(listener); 
} 

참고. 프래그먼트가 이미 업데이트 된 결과를 가지고 있기 때문에 업데이트 된 결과를 보내지 않고 만 해당 이벤트를 프래그먼트로 트리거하는 데 사용합니다. 이해가 되니?

+0

이 답변을 좋아하지만 GC에 의존하는 것은 날씨에 따라 다르다는 것을 지적해야합니다. 나는 GCed되는 것에 의존하는 알고리즘은 근본적으로 불건전하다고 주장 할 것이다. –

+0

@Eric Maxwell 의미가 있습니다. 나는 이것을 시험해보고 차이가 있는지 확인합니다. – grantka