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的调度进行了转回,错误的地方。

相关问题