2016-09-01 9 views
1

私はLoopersとRealmとのトラブルがあります。レルムとルーパーの偽善者

私はその中のonCreate Presenter()をインスタンス化Activityを持って、その後、その公開方法initFirstLaunch()の1呼び出す:

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); 
       } 
      }); 
     } 
    }); 
} 

ノートplayerViewContractは、この文脈での私の活動であることを。

私の問題はonChange()は時々(とeventualy OutOfMemoryErrorがprovoques)と呼ばれ、それはそれのブロック私のUIスレッドないときであるということです。私の推測では、私はルーパースレッドではなかったが、私がLooper.prepare()と呼ぶとき、どこかでそれが既に1つになっていると言ってクラッシュする。

何が起こっているか

おかげ


編集:追加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が、基礎となるテーブルが変更されたときに呼び出され、1回だけでなく呼び出されることを意味します。

(そしてそうto keep the autoupdate and the change listener intact even through GC, it has to be kept as a field reference、私もRealmChangeListener sはレルムのContextで弱い参照して保持されていることに注意しなければならないので、RealmObjectがある。

、また、要素が見つからない場合findFirst()はnullを返すことができることは注目に値しますが、 IDによって、それ以外の場合は直ちに要素が返されます)。playerViewContract.initWithCourseDetails(element);は何度も何度もやり直してしまい、最終的にはクラッシュするようです。

私はちょっとあなたの質問に答えましたか?

+0

状況はまだわかりません。私は 'initWithCourseDetails'への呼び出しをログに記録します。ほとんどの場合はポップしません。時には1つのログが表示されることもあります。私は 'onChange'呼び出しもログに記録します。これは常に1回呼び出されます。私は 'RealmModel'が更新されるたびに呼び出されることを理解しています、それは私が探している振る舞いです。 'initWithCourseDetails'を呼び出すと、モデルの変更が考えられたのはなぜか分かりません。純粋なビューメソッドです。 (私は 'initWithCourseDetails'コードを追加します) –

+0

あなたの' RealmChangeListener'ポイントはbtwになりました。私はそれを私のプレゼンターのフィールドに変更しました。 'onChange'が無期限と呼ばれる理由をもう一度説明してください。そして、私はあなたに大いに謝ってくれてありがとうと言いませんでした。 –

+0

テーブルを一度しか修正しないと、それは一度しか呼び出されません。しかし、 'computeTableOfContent(element);'や 'initWithCourseDetails'が何らかの形でループに陥っていない限り、コードは一度だけ呼び出されてもクラッシュしないはずです。' createObject() 'は、トランザクションで再、私は少しこのコードについてiffyだ。私の[記事](http:// medium)を読むことをお勧めしますか?あなたのレルムの使用法については、com/@ Zhuinden/how-to-use-real-for-android-like-a-champ-and-how-to-you-doing-doing-wrong-ac4f66b7f149) – EpicPandaForce