webentwicklung-frage-antwort-db.com.de

Verwenden der Call Enqueue-Funktion in Retrofit

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 Variablen Retrofit und es gab dort keine Call<T>-Schnittstelle. Dies ist das erste Mal, dass ich Retrofit verwende, und ich bekomme wiederholt null object reference. Hier ist meine Netzwerkmodellschnittstelle 

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

Und dies 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 implementiert werden soll. Auf der Retrofit-Website wird nur sehr wenig über die Verwendung des Rückrufs angegeben. Angenommen, der andere Code funktioniert einwandfrei. Hier wird das MovieResponse-Objekt von der movieDB-API zurückgegeben, die ein Array von Movies und einige zusätzliche Informationen enthält. Ich implementiere es so, dass ich, sobald ich die Antwort in MovieResponse von dort bekomme, mit der getMovies() extrahieren kann, die eine Liste der Filme zurückgibt. 

Wenn ich renne, bekomme ich einfach null object reference, weil response null ist. Ich habe versucht, nach Tutorials für die Verwendung von neuem Retrofit-2.0.0 zu suchen, insbesondere über die Verwendung der Enqueue-Funktion, aber ich habe kein Glück. Dazu noch eine Frage, wo die updateMovies() aufgerufen werden soll. Kann ich es direkt in der Hauptaktivität nennen. Führt Retrofit den Netzwerkaufruf automatisch im Hintergrund-Thread aus? 

16
AbKDs

Mit Retrofit 2 wird onResponse aufgerufen, auch wenn ein Fehler auftritt. Sie haben mit !response.isSuccess() überprüft, ob die Antwort nicht erfolgreich ist. Aber Sie haben es gerade protokolliert - wenn es wahr ist (d. H. Nicht erfolgreich). Stattdessen können Sie response.errorBody().string() protokollieren, um zu sehen, ob der API-Server den Fehler angibt, und Sie sollten etwas wie return aufrufen, um onResponse callback zu beenden, da response.body() nicht in MovieResponse umgewandelt werden konnte.

Ihr Code ist übrigens korrekt, aber wenn Sie einfach mit Retrofit beginnen, ist es einfacher, die 1.9-Version zu verwenden, da 2.0 immer noch eine Beta-Version ist (sehr stabil, aber es fehlen Tutorials).

15
guillaume_fr

Verwenden Sie einen Interceptor aus OkHttp In Retrofit 1.9 können Sie RequestInterceptor verwenden, um eine Anfrage abzufangen, die jedoch bereits in Retrofit 2.0 entfernt wurde, da die HTTP-Verbindungsschicht nach OkHttp verschoben wurde.

Daher müssen wir ab jetzt zu einem Interceptor von OkHttp wechseln. Zuerst müssen Sie es zu build.gradle hinzufügen.

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

erstellen Sie dann ein OkHttpClient-Objekt mit einem Interceptor wie folgt:

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

Übergeben Sie dann den erstellten Client an die Builder-Kette von Retrofit.

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

Entfernen Sie '/' von Ihrem @GET ("/ abc") Weil Retrofit 2.0 ein neues Konzept zur URL-Auflösung enthält. Basis-URL und @Url wurden nicht einfach nur kombiniert, sondern wurden auf dieselbe Weise aufgelöst wie stattdessen. Bitte schauen Sie sich die Beispiele unten zur Verdeutlichung an.

     

Mehr über Retrofit 2.0 erfahren

5
Abdul Rizwan

@AbKDs, ich weiß nicht, ob Sie es bereits gelöst haben, aber ich habe nach einigem Nachdenken mit Retrofit 2 herausgefunden, dass Sie " http://api.themoviedb.org " als Ihre baseUrl eingeben und die ganzer Pfad in @GET. Zum Beispiel: @GET ("/ 3/discover/movie") Dann fügen Sie Ihre Abfragen als Parameter für Ihr Interface Call hinzu.

0
daxgirl