2016-11-05 8 views
1

Я работаю с Retrofit 2 + RxAndroid, этот код работает pefect на устройствах Marshmallow и Lollipop, но не работает с устройствами kitkat.Retrofit + rxandroid вызывает ошибку stackoverflow на kitkat

@OnClick(R.id.login_btn) 
public void onLoginClicked() { 
    loginBtn.setEnabled(false); 
    AuthenticationAPI authApi = ServiceCreator.createService(AuthenticationAPI.class, null); 
    authApi.login(new LoginUserRequest(emailEditText.getText().toString(), passwordEditText.getText().toString())) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(verifyEmailResponse -> Log.i("TEST", "onNext: " + verifyEmailResponse.success), 
      throwable -> { 
      handleError(throwable); 
      loginBtn.setEnabled(true); 
      }); 
} 

ServiceCreator.java

public class ServiceCreator { 

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 
    private static final int DEFAULT_TIMEOUT = 30; //seconds 

    private static Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create(); 
    private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()); 

    private static Retrofit.Builder builder = new Retrofit.Builder() 
      .baseUrl(BuildConfig.REST_BASE_ENDPOINT) 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .addCallAdapterFactory(rxAdapter); 

    public static <RESTService> RESTService createService(Class<RESTService> service, String userToken) { 

     if (BuildConfig.REST_DEBUG) { 
      HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
      logging.setLevel(HttpLoggingInterceptor.Level.BODY); 
      httpClient.addInterceptor(logging); 
     } 

     if (StringUtils.isNotBlank(userToken)) { 
      httpClient.addInterceptor(chain -> { 
       Request original = chain.request(); 

       Request request = original.newBuilder() 
         .header(Constants.AUTHORIZATION_HEADER, userToken) 
         .method(original.method(), original.body()) 
         .build(); 
       return chain.proceed(request); 
      }); 
     } 

     httpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 
     httpClient.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 
     httpClient.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 

     Retrofit retrofit = builder.client(httpClient.build()).build(); 
     return retrofit.create(service); 
    } 

    public static Retrofit retrofit() { 
     return builder.client(httpClient.build()).build(); 
    } 
} 

Ошибка:

FATAL EXCEPTION: RxNewThreadScheduler-1 java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread. 
    at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
    at java.lang.Thread.run(Thread.java:841) 
Caused by: java.lang.StackOverflowError 
    at org.apache.harmony.security.asn1.ASN1StringType.getDecodedObject(ASN1StringType.java:99) 
    at org.apache.harmony.security.asn1.ASN1StringType.decode(ASN1StringType.java:90) 
    at org.apache.harmony.security.asn1.ASN1Choice.decode(ASN1Choice.java:308) 
    at org.apache.harmony.security.x501.AttributeTypeAndValue$1.decode(AttributeTypeAndValue.java:339) 
    at org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInputStream.java:554) 
    at org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInputStream.java:105) 
    at org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.java:40) 
    at org.apache.harmony.security.asn1.BerInputStream.decodeValueCollection(BerInputStream.java:626) 
    at org.apache.harmony.security.asn1.BerInputStream.readSetOf(BerInputStream.java:606) 
    at org.apache.harmony.security.asn1.DerInputStream.readSetOf(DerInputStream.java:115) 
    at org.apache.harmony.security.asn1.ASN1SetOf.decode(ASN1SetOf.java:40) 
    at org.apache.harmony.security.asn1.BerInputStream.decodeValueCollection(BerInputStream.java:626) 
    at org.apache.harmony.security.asn1.BerInputStream.readSequenceOf(BerInputStream.java:584) 
    at org.apache.harmony.security.asn1.ASN1SequenceOf.decode(ASN1SequenceOf.java:40) 
    at org.apache.harmony.security.asn1.ASN1Type.decode(ASN1Type.java:82) 
    at javax.security.auth.x500.X500Principal.<init>(X500Principal.java:78) 
    at com.android.org.conscrypt.OpenSSLX509Certificate.getIssuerX500Principal(OpenSSLX509Certificate.java:422) 
    at com.android.org.conscrypt.OpenSSLX509Certificate.getIssuerDN(OpenSSLX509Certificate.java:236) 
    at com.android.org.conscrypt.TrustManagerImpl.cleanupCertChainAndFindTrustAnchors(TrustManagerImpl.java:340) 
    at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:225) 
    at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202) 
    at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:611) 
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405) 
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:241) 
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:198) 
    at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174) 
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114) 
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:193) 
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129) 
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98) 
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 

Спасибо!

// UPDATE: Я обнаружил, которые вызывают ошибку, но не решение, я создал проблему в https://github.com/square/okhttp/issues/2962

ответ

1

ошибка происходит потому, что я добавлял тот же перехватчик снова и снова, новая версия может быть ,

public class ServiceCreator { 

    private OkHttpClient.Builder httpClient; 
    private static final int DEFAULT_TIMEOUT = 30; //seconds 

    private Gson gson; 
    private RxJavaCallAdapterFactory rxAdapter; 
    private Retrofit.Builder builder; 

    private static ServiceCreator mInstance = null; 

    private ServiceCreator() { 
     httpClient = new OkHttpClient.Builder(); 
     gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create(); 
     rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()); 
     builder = new Retrofit.Builder() 
       .baseUrl(BuildConfig.REST_BASE_ENDPOINT) 
       .addConverterFactory(GsonConverterFactory.create(gson)) 
       .addCallAdapterFactory(rxAdapter); 

     if (BuildConfig.REST_DEBUG) { 
      HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
      logging.setLevel(HttpLoggingInterceptor.Level.BODY); 
      httpClient.addInterceptor(logging); 
     } 
    } 

    public static ServiceCreator getInstance() { 
     if (mInstance == null) { 
      mInstance = new ServiceCreator(); 
     } 
     return mInstance; 
    } 

    public <RESTService> RESTService createService(Class<RESTService> service, String userToken) { 

     if (StringUtils.isNotBlank(userToken)) { 
      httpClient.addInterceptor(chain -> { 
       Request original = chain.request(); 

       Request request = original.newBuilder() 
         .header(Constants.AUTHORIZATION_HEADER, userToken) 
         .method(original.method(), original.body()) 
         .build(); 
       return chain.proceed(request); 
      }); 
     } 

     httpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 
     httpClient.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 
     httpClient.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 

     Retrofit retrofit = builder.client(httpClient.build()).build(); 
     return retrofit.create(service); 
    } 

    public Retrofit retrofit() { 
     return getInstance().builder.client(getInstance().httpClient.build()).build(); 
    } 
} 
+0

Большое спасибо, это спасло мой день, я столкнулся с той же проблемой. –

0

Это одна из самых тривиальных проблем, связанных с OkHttp и модификацией. На самом деле, я тоже долго боролся за решение, пока не уловил ошибку, вызванную следующим блоком кода.

HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
logging.setLevel(HttpLoggingInterceptor.Level.BODY); 
httpClient.addInterceptor(logging); 

Поэтому, как только вы удаляете линии, он должен нормально работать.

Смежные вопросы