2

RXをAndroidに適用しようとしています。ボタンをクリックしたときに、ウェブから何かをダウンロードして表示したいとき。バックグラウンドスレッドで機能が実行されない

私の問題は、HttpClient.connect()は、背景の代わりに mainThreadで実行されます。 HttpClient.connect()の呼び出し(Observable.mapに渡された関数として実行される)

Observable<Integer> dayDeltas = Obs.obsToSequence(Obs.Observable(textView)); //transforms click events to observable 
Observable<String> dates = dayDeltas.map(...).map(...) 
dates.map(Obs.dateToWebPage()) // calls http.connect() 
    .map(Obs.parseEvents()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribeOn(Schedulers.newThread()) 
    .subscribe(updateTextView(textView)); 

public static Observable<Object> Observable(final TextView text) { 
     return Observable.create(new Observable.OnSubscribe<Object>() { 
      @Override 
      public void call(final Subscriber<? super Object> subscriber) { 
       final Object event = new Object(); 
       text.setOnClickListener(new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         Log.e("click", "click"); 
         subscriber.onNext(event); 
        } 
       }); 
      } 
     }); 

今私の素朴な解釈があるため、私は.subscribeOn(Schedulers.newThreadを())があるということですすべての関数/ observable上の演算子は、.map(f)を含む新しいスレッドで実行する必要があります。明らかにこれは起こっていることではないので、このチェーンのどの部分が新しいスレッドで実行されますか?

答えて

4

subscribeOnサブスクリプションの副作用を引き起こすことがあります。設定では、コールバックを登録して新しいスレッドのボタン押下をキャプチャしますが、押下が発生するとonNextエミッションがメインスレッドによってトリガされます。ネットワーク接続を含むチェーンは、メインスレッド上で実行されます。

接続方法の前に新しいobserveOn(Schedulers.io())を追加する必要があります。これは、ボタンプレスイベントの受信がメインスレッドから行われることを確認するためです。

編集:

//transforms click events to observable 
Observable<Integer> dayDeltas = Obs.obsToSequence(Obs.Observable(textView)); 

Observable<String> dates = dayDeltas.map(...).map(...) 
dates 
.observeOn(Schedulers.io()) // <------------------------------------------ add 
.map(Obs.dateToWebPage()) // calls http.connect() 
.map(Obs.parseEvents()) 
.observeOn(AndroidSchedulers.mainThread()) 
//.subscribeOn(Schedulers.newThread()) // <------------------------------- remove 
.subscribe(updateTextView(textView)); 
+1

Iは.connect上方obserOn(newThread)を入れてみました()関数 dates.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()) .MAP(Obs.dateToWebPage()) 私同じエラーが発生する:android.os.NetworkOnMainThreadException – Blitzkr1eg

+0

あなたは間違っている。編集を参照してください。 – akarnokd

2

慎重Scheduling and Threading RX docを読んだ後、私は解決策があります:私の元のコードで

dates 
     .observeOn(Schedulers.io()) 
     .subscribeOn(AndroidSchedulers.mainThread()) 
     .map(Obs.dateToWebPage()) 

を、observeOn/subscribeOnに渡されたスケジューラが逆転していました間違った場所。

関連する問題