2016-03-03 16 views
7

Ich benutze Retrofit 2 (Beta 4), und ich wollte von der Verwendung der Standard Call Antwort auf die RxAndroid Observable Antwort zu bewegen. Es ist mir gelungen, die meisten meiner Anrufe mit einem einfachen Wechsel von Call<List<ExampleObject>> zu Observable<List<ExampleObject>> zu wechseln. Ein paar meiner Anrufe verwenden Call<okhttp3.ResponseBody>, die großen Werke, aber wenn ich Call ausgelagert wurde ich mit einem Fehler begegnet:Wie Antwort Antwort Körper mit RxAndroid und Retrofit 2?

03-03 15:21:44.237 27333-27333/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main 
     Process: com.example.app, PID: 27333 
     java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable<okhttp3.ResponseBody> 
      for method AuthenticationService.getLoginForm 
      at retrofit2.Utils.methodError(Utils.java:119) 
      at retrofit2.MethodHandler.createCallAdapter(MethodHandler.java:52) 
      at retrofit2.MethodHandler.create(MethodHandler.java:25) 
      at retrofit2.Retrofit.loadMethodHandler(Retrofit.java:164) 
      at retrofit2.Retrofit$1.invoke(Retrofit.java:145) 
      at java.lang.reflect.Proxy.invoke(Proxy.java:393) 
      at $Proxy6.getLoginForm(Unknown Source) 
      at com.example.app.ui.fragment.LoginFragment.login(LoginFragment.java:214) 
      at com.example.app.ui.fragment.LoginFragment.lambda$onContinue$1(LoginFragment.java:168) 
      at com.example.app.ui.fragment.LoginFragment.access$lambda$1(LoginFragment.java) 
      at com.example.app.ui.fragment.LoginFragment$$Lambda$4.onClick(Unknown Source) 
      at android.view.View.performClick(View.java:5204) 
      at android.view.View$PerformClick.run(View.java:21153) 
      at android.os.Handler.handleCallback(Handler.java:739) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:148) 
      at android.app.ActivityThread.main(ActivityThread.java:5417) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable<okhttp3.ResponseBody>. 
     Tried: 
      * retrofit2.ExecutorCallAdapterFactory 
      at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:230) 
      at retrofit2.Retrofit.callAdapter(Retrofit.java:194) 
      at retrofit2.MethodHandler.createCallAdapter(MethodHandler.java:50) 
       ... 18 more 

Der Grund, warum ich die ResponseBody anstelle eines anderen Objekts wie gewöhnlich verwende, ist, weil in In diesen Fällen muss ich HTML analysieren, und soweit ich weiß, gibt es keinen Retrofit-Konverter für einen HTML-Parser. Ich weiß, dass ich wahrscheinlich selbst eine erstellen könnte, aber ich möchte nicht für die kleine Menge HTML, die ich analysieren muss.

Meine Frage ist, warum unterstützt der Retrofit 2 RxJava Adapter nicht ResponseBody, wenn Retrofit 2 selbst tut? Gibt es eine andere Möglichkeit, den Antwortstring von einem Observable zu erhalten?


Mein Service:

public interface AuthenticationService() { 

    @GET("cas/login") 
    Observable<Response<ResponseBody>> login(); 
} 

Relevante Retrofit-Code:

public static Retrofit getRetrofit() { 
    if(mRetrofit == null) { 
     return new Retrofit.Builder() 
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
       .addConverterFactory(GsonConverterFactory.create(getGson())) 
       .client(getOkHttpClient()) 
       .build(); 
    } return mRetrofit; 
} 

public static AuthenticationService getAuthenticationService() { 
    return getRetrofit().create(AuthenticationService.class); 
} 

Antwortversuch:

private void login() { 
    RestClient.getAuthenticationService().login() 
      .observeOn(ASchedulers.newThread()) 
      .subscribeOn(AndroidSchedulers.mainThread()) 
      .doOnNext(this::onLoginResponse); 
} 

private void onLoginResponse(Response<ResponseBody>> response) { 
    try { 
     parseResponse(response.body().string()); 
    } catch (IOException) { 
     Timber.w(throwable, "Failed to login"); 
    } 
} 

New Stack-Trace:

03-03 16:14:57.848 26866-26866/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main 
     Process: com.example.app, PID: 26866 
     java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable<retrofit2.Response<okhttp3.ResponseBody>> 
      for method AuthenticationService.getLoginForm 
      at retrofit2.Utils.methodError(Utils.java:119) 
      at retrofit2.MethodHandler.createCallAdapter(MethodHandler.java:52) 
      at retrofit2.MethodHandler.create(MethodHandler.java:25) 
      at retrofit2.Retrofit.loadMethodHandler(Retrofit.java:164) 
      at retrofit2.Retrofit$1.invoke(Retrofit.java:145) 
      at java.lang.reflect.Proxy.invoke(Proxy.java:393) 
      at $Proxy3.getLoginForm(Unknown Source) 
      at com.example.app.ui.fragment.LoginFragment.login(LoginFragment.java:206) 
      at com.example.app.ui.fragment.LoginFragment.lambda$onContinue$1(LoginFragment.java:160) 
      at com.example.app.ui.fragment.LoginFragment.access$lambda$1(LoginFragment.java) 
      at com.example.app.ui.fragment.LoginFragment$$Lambda$4.onClick(Unknown Source) 
      at android.view.View.performClick(View.java:5204) 
      at android.view.View$PerformClick.run(View.java:21153) 
      at android.os.Handler.handleCallback(Handler.java:739) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:148) 
      at android.app.ActivityThread.main(ActivityThread.java:5417) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable<retrofit2.Response<okhttp3.ResponseBody>>. 
     Tried: 
      * retrofit2.ExecutorCallAdapterFactory 
      at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:230) 
      at retrofit2.Retrofit.callAdapter(Retrofit.java:194) 
      at retrofit2.MethodHandler.createCallAdapter(MethodHandler.java:50) 
       ... 18 more 
+1

Bitte den eigentlichen Code schreiben. –

+0

@TudorLuca Aktualisiert mit Code – Bryan

+0

@TudorLuca Es tut mir leid, dass Sie Ihre Zeit verschwendet haben. Ich habe herausgefunden, dass ich tatsächlich ein Retrofit-Objekt (das ich hätte löschen sollen) benutzt, das keine RxJavaCallAdapterFactory hatte. Ich zerreiße den aktuellen Code und es ist ein bisschen durcheinander. Danke für deine Hilfe trotzdem. – Bryan

Antwort

16

versuchen, etwas wie folgt aus:

import okhttp3.ResponseBody; 
import retrofit2.Response; 

@GET("/whatever") 
Observable<Response<ResponseBody>> getWhatever(); 

bearbeiten: Vergessen Sie nicht, dass Sie den Adapter für RxJava angeben müssen:

new Retrofit.Builder() 
      ... 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .build() 
      .create(Api.class); 
+0

Versucht, das gleiche Ergebnis:/Ich versuchte auch eine einfache 'okhttp3.Respone', die auch nicht funktioniert. – Bryan

+0

Ja, ich habe die 'RxJavaCallAdapterFactory' korrekt eingerichtet, da meine anderen' Observable ' Antworten wie erwartet funktionieren. – Bryan

+2

Es wird nicht mit okhttp3.Respone funktionieren, benötigen Sie Retrofit's Response. –