2

我試圖將RX應用到Android。我想要一個按鈕被點擊時,從網上下載並顯示它。函數不在後臺線程上執行

我的問題是,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); 
        } 
       }); 
      } 
     }); 

我們HttpClient.connect()的調用執行我的天真的解釋是,因爲我已經.subscribeOn(Schedulers.newThread())每個函數/運算符應該在一個新的線程中執行,包括.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

我試圖把obserOn(newThread)的.connect()函數 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的調度進行了轉回,錯誤的地方。

相關問題