2015-12-18 21 views
11

Tôi nhận ra rằng tôi đang sử dụng subscribeOn()/observOn() trên MainThread. Các tùy chọn nào tôi có thể chuyển vào subscribeOn()? Tập hợp các tùy chọn mà tôi có thể chuyển vào observOn() là gì?RxJava và 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()); 
      } 
     }); 
    } 
} 
+0

cố gắng để làm '.subscribeOn (Schedulers.newThread())'. điều này sẽ thực thi Observable trong Thread mới. –

Trả lời

24

Viết lại phần cuối của mã của bạn để:

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

quan trọng lưu ý từ @akarnokd:

Đáng nói rằng người ta cần đến chuỗi các cuộc gọi như ở đây vì Quan sát không phải là mẫu trình tạo (nơi bạn sửa đổi cài đặt của đối tượng hiện có)

+3

Đáng nói rằng một trong những nhu cầu để chuỗi các cuộc gọi như ở đây vì Observable không phải là mô hình xây dựng (nơi bạn sửa đổi các thiết lập của một đối tượng hiện có). – akarnokd

+1

Giải thích cũng đáng nhắc đến. Tại sao OP nên viết lại như thế này, tại sao biến thể của bạn lại đúng? Tôi không tự hỏi. Một câu trả lời hay nên có điều này. –

+1

Bất kỳ ý tưởng làm thế nào để làm điều này với RxJava 2? – Incinerator

7

Bạn nên gọi Observable.unsubscribeOn(Schedulers.io()), retrofit sẽ hủy đăng ký ở cuối yêu cầu http.

Trong RxJavaCallAdapterFactory của retrofit-rxjava-adapter

nó hành động như thế này.

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

Nhưng khi subscriber là một SafeSubscriber, nó sẽ gọi unsubscribe cuối cùng.

Tôi gặp sự cố này trong ứng dụng của mình.

Full mã:

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

yep, đó là giải pháp ở đây: https://github.com/square/retrofit/issues/1328 - điều này dường như sẽ được sửa trong phiên bản phát hành của trang bị thêm 2, sau khi okhttp 2.7 xuất hiện (nó đã xuất hiện) . – ahmedre

+2

@ahmedre họ sẽ không bao giờ ... 'Đó không phải là một vấn đề trang bị thêm hoặc OkHttp' – Inoy

Các vấn đề liên quan