2016-09-01 4 views
1

나는 루퍼와 렐름에 문제가있다. 렐름과 루퍼 헛소리

내가

가 실체화 Activity이 그것에서 onCreate()에서 Presenter하고 공개 방법 initFirstLaunch() 중 하나 전화 : playerViewContract이 상황에서 내 활동이라고

RealmChangeListener<CourseDetailed> listener = new RealmChangeListener<CourseDetailed>() { 
    @Override 
    public void onChange(CourseDetailed element) { 
     Log.i("renaud", "courseDetailed.addChangeListener onChange"); 
     computeTableOfContent(element); 
     Log.i("renaud", "1"); 
     playerViewContract.initWithCourseDetails(element); 
     Log.i("renaud", "2"); 
    } 
}; 

public void initFirstLaunch() { 

    courseDetailed = realm.where(CourseDetailed.class).contains("_id", courseId).findFirst(); 

    if (courseDetailed == null) { 
     courseDetailed = realm.createObject(CourseDetailed.class, courseId); 
    } 

    courseDetailed.addChangeListener(listener); 

    Api.getInstance().backend.getCourse(courseId).enqueue(new CustomRetrofitCallBack<CourseDetailed>(playerViewContract) { 
     @Override 
     public void onResponseReceived(final CourseDetailed response) { 

      Realm.getDefaultInstance().executeTransactionAsync(new Realm.Transaction() { 
       @Override 
       public void execute(Realm realm) { 
        realm.copyToRealmOrUpdate(response); 
       } 
      }); 
     } 
    }); 
} 

메모를.

내 문제는 onChange()라는 때때로 것을, 그리고 그것을 블록 내 UI 스레드를 수행 할 때 (eventualy과 OutOfMemoryError을 provoques). 내 추측은 루퍼 스레드가 아니라는 것입니다. 그러나 Looper.prepare()을 호출하면 어디에서든지 이미 하나에 있음을 알리는 충돌이 발생합니다.

무슨 일입니까?

감사


편집 : 추가 initWithCourseDetailed 코드

@Override 
public void initWithCourseDetails(final CourseDetailed detailed) { 

    Log.i("renaud", "initWithCourseDetails"); 

    mDrawer.post(new Runnable() { 
     @Override 
     public void run() { 

      String title = detailed.getName(); 
      String subtitle = detailed.getCompany().getName(); 

      if (detailed.getThumbnail() != null) { 

       String picUrl = AppConstants.SERVER_URL + "/api/" + detailed.getThumbnail(); 

       final LinearLayout l = (LinearLayout) mNavigationView.findViewById(R.id.layout); 
       Picasso.with(ModulePlayerActivity.this) 
         .load(picUrl) 
         .config(Bitmap.Config.RGB_565) 
         .into(new Target() { 
          @Override 
          public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { 
           l.setBackground(new BitmapDrawable(getResources(), bitmap)); 
          } 

          @Override 
          public void onBitmapFailed(Drawable errorDrawable) { 
          } 

          @Override 
          public void onPrepareLoad(Drawable placeHolderDrawable) { 

          } 
         }); 
      } 

      TextView nameTv = (TextView) mNavigationView.findViewById(R.id.drawer_header_name); 
      nameTv.setText(title); 

      TextView jobTv = (TextView) mNavigationView.findViewById(R.id.drawer_header_job); 
      jobTv.setText(subtitle); 

      supportInvalidateOptionsMenu(); 

     } 
    }); 
} 

편집 : 보정

Api.getInstance().backend.getCourse(courseId).enqueue(new CustomRetrofitCallBack<CourseDetailed>(playerViewContract) { 
      @Override 
      public void onResponseReceived(final CourseDetailed response) { 

       //TEST 
       Realm realm = null; 
       try { 
        realm = Realm.getDefaultInstance(); 
        realm.executeTransactionAsync(new Realm.Transaction() { 
         @Override 
         public void execute(Realm realm) { 
          realm.copyToRealmOrUpdate(response); 
         } 
        }); 
       } finally { 
        if (realm != null) { 
         realm.close(); 
        } 
        realm = null; 
       } 

      } 
     }); 

답변

1

UI 스레드 인 루퍼 (는 루퍼를 가지고 Looper.getMainLooper()), 자동 업데이트가 있음을 의미합니다. 그러나 자동 업데이트는 RealmObject에 추가하는 ChangeListener이 기본 테이블이 수정 될 때마다 호출된다는 것을 의미합니다.

(그리고 나는 또한 RealmChangeListener의이 영역의 Context에 의해 약한 참조하여 유지하고 너무 너무 to keep the autoupdate and the change listener intact even through GC, it has to be kept as a field referenceRealmObject입니다되어 있음을 알아 두셔야합니다.

을 그것도 findFirst()가 null 반환 할 수 있음을 주목할 필요가 있지만 요소가 발견되지 않는 경우 ID별로, 그렇지 않으면 즉시 요소를 반환합니다.)

따라서 어떤 것이 든 playerViewContract.initWithCourseDetails(element);이 되풀이해서 결국 충돌합니다.

내가 귀하의 질문에 답변 해 주셨으면 좋겠습니까?

+0

아직 명확하지 않은 점이 있습니다. 'initWithCourseDetails'에 대한 호출을 기록하고, 대부분의 시간에 팝업하지 않습니다. 때로는 1 로그를 보게됩니다. 또한 항상 호출되는 onChange 호출을 기록합니다. 나는'RealmModel'이 업데이트 될 때마다 호출된다는 것을 이해합니다. 즉, 제가 찾고있는 동작입니다. 'initWithCourseDetails'를 호출하면 내 모델 변경을 생각하는 이유를 이해할 수 없습니다. 순수한 뷰 메소드입니다. ('initWithCourseDetails' 코드를 추가합니다.) –

+0

'RealmChangeListener' 포인트를 가져 왔습니다. 필자는 그것을 내 발표자의 필드로 변경했습니다. 'onChange'가 무한 시대라고 불리는 이유를 다시 설명해 주시겠습니까? 그리고 내가 크게 대답했다는 것을 당신에게 고맙다고 말하지 않았다는 것을 깨달았습니다. 나는 당신에게 확신합니다. –

+0

테이블을 한 번만 수정하면 기술적으로 한 번만 호출해야합니다. 그러나 'computeTableOfContent (element);'또는'initWithCourseDetails'가 어떻게 든 루프에 걸리지 않는 한, 코드가 한 번만 호출되면 코드가 충돌해서는 안됩니다 ... 'createObject()'가 작동하지 않아야합니다. 트랜잭션에서, 그래서 나는이 코드에 대해 약간의 iffy. 내 [기사] (http : // 매체.com/@ Zhuinden/how-to-use-realm-for-android-like-a-champ-and-how-to-youre-doing-it-wrong-ac4f66b7f149) – EpicPandaForce