2015-09-07 15 views
15

Ich verwende Retrofit-2.0.0 für meine App. Jetzt basiert jedes Tutorial zu Retrofit, das ich im Web gefunden habe, auf früheren Retrofit und es gab keine Call<T> Schnittstelle dort. Dies ist das erste Mal, dass ich Retrofit verwende und ich bekomme wiederholt null object reference. Hier ist mein Netzwerk-Modell-SchnittstelleVerwenden von Call Enqueue Funktion in Retrofit

public interface TMovieDBService { 
    @GET("/movie") 
    Call<MovieResponse> getMovieResponse(@Query("sort_by") String sortKey, 
          @Query("api_key") String apiKey); 
} 

Und das ist meine updateMovies() Funktion, die die Liste der Filme aktualisiert.

void updateMovies() { 
    Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("http://api.themoviedb.org/3/discover") 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build(); 

    String sortKey = "popularity.desc"; 
    TMovieDBService service = retrofit.create(TMovieDBService.class); 

    Call<MovieResponse> call = service.getMovieResponse(sortKey, ApiKey.API_KEY); 

    call.enqueue(new Callback<MovieResponse>() { 
     @Override 
     public void onResponse(Response<MovieResponse> response) { 
      Log.d(LOG_TAG, "Reached this place"); 
      if (!response.isSuccess()) { 
       Log.d(LOG_TAG, "No Success"); 
      } 
      mMovieList = response.body().getMovies(); // <- response is null here 
      // Log.d(LOG_TAG, "Couldn't not reach this place"); 
      mMovieAdapter.notifyDataSetChanged(); 
      Log.d(LOG_TAG, "Response returned by website is : " + response.code()); 
     } 

     @Override 
     public void onFailure(Throwable t) { 
      // Toast for the moment 
      // Appropriate error handling code should be present here 
      Toast.makeText(getActivity(), "Failed !", Toast.LENGTH_LONG).show(); 
     } 
    }); 
} 

Ich weiß nicht, was in der Enqueue-Funktion zu implementieren ist. Auf der Retrofit-Website wird nur sehr wenig über die Verwendung des Rückrufs berichtet. Angenommen, der gesamte andere Code funktioniert einwandfrei. Hier wird MovieResponse Objekt von der MovieDB-API zurückgegeben, die ein Array von Movie s und einige zusätzliche Informationen enthält. Ich implementiere es so, dass, sobald ich die Antwort in MovieResponse von dort bekomme ich extrahieren kann mit der getMovies(), die eine Liste von Filmen zurückgeben wird.

Wenn ich laufe ich einfach null object reference, weil response ist null. Ich habe versucht, Tutorials zur Verwendung von neuen Retrofit-2.0.0 insbesondere auf Enqueue-Funktion zu suchen, aber ich bin kein Glück. Plus eine weitere Frage wo sollte der updateMovies() aufgerufen werden. Kann ich es direkt in der Mainactivity nennen. Führt Retrofit den Netzwerkanruf automatisch auf Hintergrundthread aus?

+0

https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta1 ↑ Diese Beta-Version ist, so dass ich denke, Sie sollten Verwenden Sie stattdessen die Retrofit-Version 1.9.0 (die neueste stabile Release-Version). –

+0

Ich bin auch mit dem gleichen Problem konfrontiert. Hast du irgendeine Lösung? – Govan

+0

Ähnliche Fragen und Antworten: http://stackoverflow.com/questions/33202871/retrofit-error-2-0-2-beta-error-in-callback-does-not-override-abstract-method-on –

Antwort

14

Mit Retrofit 2 wird onResponse aufgerufen, auch wenn ein Fehler vorliegt. Sie haben überprüft, ob die Antwort nicht erfolgreich ist, indem Sie !response.isSuccess() verwenden. Aber Sie haben es gerade eingeloggt - wenn es wahr ist (d. H. Nicht erfolgreich). Stattdessen könnten Sie response.errorBody().string() protokollieren, um zu sehen, ob der api-Server den Fehler angibt, und Sie sollten beispielsweise return aufrufen, um onResponse Callback zu beenden, da response.body() nicht in MovieResponse umgewandelt werden konnte, daher die Null-Ausnahme.

Übrigens, Ihr Code ist korrekt, aber wenn Sie einfach mit Retrofit anfangen, wäre es einfacher, Version 1.9 zu verwenden, da 2.0 immer noch eine Betaversion ist (sehr stabil, aber Mangel an Tutorials).

+0

Verwenden Sie dies Ich habe den Fehler herausgefunden. Meine Post-Anfrage wird als GET-Anfrage veröffentlicht. Brauchen Sie die Ursache zu finden. Trotzdem danke. Es hilft. – Govan

+1

'response.isSuccess()' wird in Retrofit 2 auch in 'response.isSuccessful()' geändert. – Marlon

0

@AbKDs, ich weiß nicht, ob Sie es bereits gelöst haben, aber ich habe nach einigen Schwierigkeiten mit Retrofit 2 herausgefunden, dass Sie "http://api.themoviedb.org" als Ihre BaseUrl setzen und den gesamten Pfad in @GET hinzufügen müssen. Wie folgt: @GET ("/ 3/discover/movie") Und dann fügen Sie Ihre Abfragen als Parameter für Ihre Schnittstelle Call.

4

Verwenden Sie einen Interceptor von OkHttp Bei Retrofit 1.9 konnten Sie RequestInterceptor verwenden, um eine Anforderung abzufangen, aber sie wurde bereits bei Retrofit 2.0 entfernt, da die HTTP-Verbindungsebene nach OkHttp verschoben wurde.

Als Ergebnis müssen wir ab jetzt auf einen Interceptor von OkHttp wechseln. Zuerst müssen Sie es zu build.gradle hinzufügen

compile 'com.squareup.okhttp:okhttp:2.5.0' 

und erstellen Sie ein OkHttpClient Objekt mit einem Interceptor wie folgt aus:

OkHttpClient client = new OkHttpClient(); 
    client.interceptors().add(new Interceptor() { 
     @Override 
     public Response intercept(Chain chain) throws IOException { 
      Response response = chain.proceed(chain.request()); 
      // Do anything with response here 
      return response; 
     } 
    }); 

Und dann das erstellte Client in Retrofit der Builder-Kette übergeben.

Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.themoviedb.org/3/discover/").addConverterFactory(GsonConverterFactory.create()).client(client).build(); 

entfernen '/' aus dem @ abrufen ("/ abc") weil Retrofit 2.0 kommt mit neuen URL-Konzept zu lösen. Base URL und @Url wurden nicht einfach miteinander kombiniert, sondern wurden genauso gelöst wie das, was stattdessen getan wird. Bitte beachten Sie die folgenden Beispiele zur Verdeutlichung.

To know more about Retrofit 2.0