2015-12-18 26 views
11

MainThreadでsubscribeOn()/ observeOn()を使用しています。 subscribeOn()に渡すことができるオプションのセットは何ですか? observeOn()に渡すことができるオプションのセットは何ですか?RxJavaとRetrofit2:NetworkOnMainThreadException

12-17 21:36:09.154 20550-20550/rx.test D/MainActivity2: [onCreate] 
12-17 21:36:09.231 20550-20550/rx.test D/MainActivity2: starting up observable... 
12-17 21:36:09.256 20550-20550/rx.test D/MainActivity2: [onError] 
12-17 21:36:09.256 20550-20550/rx.test W/System.err: android.os.NetworkOnMainThreadException 

GovService.java

import java.util.List; 
import retrofit.Call; 
import retrofit.http.GET; 
import rx.Observable; 

public interface GovService { 
    @GET("/txt2lrn/sat/index_1.json") 
    Observable<MyTest> getOneTestRx(); 
} 

MyTest.java

public class MyTest { 
    private String name, url; 
    private int num; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getUrl() { 
     return url; 
    } 

    public void setUrl(String url) { 
     this.url = url; 
    } 

    public int getNum() { 
     return num; 
    } 

    public void setNum(int num) { 
     this.num = num; 
    } 

    @Override 
    public String toString() { 
     return "Name: " + this.name + ", num: " + this.num + ", url: " + this.url; 
    } 
} 

MainActivity2.java

import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.DefaultItemAnimator; 
import android.support.v7.widget.LinearLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.support.v7.widget.Toolbar; 
import android.util.Log; 

import retrofit.GsonConverterFactory; 
import retrofit.Retrofit; 
import retrofit.RxJavaCallAdapterFactory; 
import rx.Observable; 
import rx.Subscriber; 
import rx.android.schedulers.AndroidSchedulers; 
import rx.schedulers.Schedulers; 

public class MainActivity2 extends AppCompatActivity { 
    private final String TAG = getClass().getSimpleName(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Log.d(TAG, "[onCreate]"); 
     setContentView(R.layout.activity_main); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     RecyclerView mRV = (RecyclerView) findViewById(R.id.rv); 
     mRV.setLayoutManager(new LinearLayoutManager(this));// setup LayoutManager 
     mRV.setItemAnimator(new DefaultItemAnimator());// setup ItemAnimator 

     // setup retrofit 
     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl("http://goanuj.freeshell.org") 
       .addConverterFactory(GsonConverterFactory.create()) 
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
       .build(); 
     GovService service = retrofit.create(GovService.class); 

     Log.d(TAG, "starting up observable..."); 
     Observable<MyTest> o = service.getOneTestRx(); 
     o.subscribeOn(Schedulers.io()); 
     o.observeOn(AndroidSchedulers.mainThread()); 
     o.subscribe(new Subscriber<MyTest>() { 
      @Override 
      public void onCompleted() { 
       Log.d(TAG, "[onCompleted] "); 
      } 

      @Override 
      public void onError(Throwable t) { 
       Log.d(TAG, "[onError] "); 
       t.printStackTrace(); 
      } 

      @Override 
      public void onNext(MyTest m) { 
       Log.d(TAG, "[onNext] " + m.toString()); 
      } 
     }); 
    } 
} 
@akarnokdから

service.getOneTestRx() 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(new Subscriber<MyTest>() { 
     @Override 
     public void onCompleted() { 
      Log.d(TAG, "[onCompleted] "); 
     } 

     @Override 
     public void onError(Throwable t) { 
      Log.d(TAG, "[onError] "); 
      t.printStackTrace(); 
     } 

     @Override 
     public void onNext(MyTest m) { 
      Log.d(TAG, "[onNext] " + m.toString()); 
     } 
    }); 

重要な注意

+0

は '' .subscribeOn(Schedulers.newThreadを())を実行してみてください。これは新しいスレッドでObservableを実行します。 –

答えて

24
はにあなたのコードの最後の部分を書き換え

観察可能ではない ので、1つのように、ここでチェーンへの呼び出しを必要と言及する価値ビルダーパターン(既存のオブジェクトの設定 を変更する場所)

+3

Observableはビルダーパターン(既存のオブジェクトの設定を変更する場所)ではないため、ここでは呼び出しをチェーン化する必要があると述べる価値があります。 – akarnokd

+1

説明も重要です。なぜOPがこのように書き直されるべきですか、あなたの異形はどうして正しいですか?私は自分自身を求めていません。良い答えがこれを持っている必要があります。 –

+1

RxJava 2でこれを行うにはどうすればよいですか? – Incinerator

7

httpリクエストの最後にObservable.unsubscribeOn(Schedulers.io())retrofitに退会する必要があります。このようなretrofit-rxjava-adapter

そのアクションのRxJavaCallAdapterFactory

if (!subscriber.isUnsubscribed()) { 
    subscriber.onCompleted(); 
} 

しかしsubscriberSafeSubscriberあるとき、それは最終的にunsubscribeを呼ぶことにします。

私のアプリでこの問題があります。

全コード:

o.subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .unsubscribeOn(Schedulers.io()); 
+1

これも解決策です:https://github.com/square/retrofit/issues/1328 - okhttp 2.7がリリースされた後(すでにリリースされています)、これは改造2のリリース版ではっきりと修正されます。 。 – ahmedre

+2

@ahmedre彼らは決して...「改造やOkHttpの問題ではない」 – Inoy

関連する問題