Использование функции "Завершение вызова" в "Дооснащении"

Я использую Retrofit-2.0.0 для своего приложения. Теперь каждый учебник по Retrofit, который я нашел в Интернете, основан на более раннем Retrofit и там не было интерфейса Call<T>. Это первый раз, когда я использую Retrofit, и я неоднократно получаю null object reference. Вот мой интерфейс сетевой модели

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

И это моя функция updateMovies(), которая обновляет список фильмов.

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

Я не знаю, что реализовать в функции enqueue. На обновленном веб-сайте очень мало информации о том, как использовать обратный вызов. Предположим, что все остальные коды работают нормально. Здесь объект MovieResponse возвращается API-интерфейсом movieDB, который содержит массив Movie и некоторую дополнительную информацию. Я реализую его таким образом, чтобы после получения ответа от MovieResponse оттуда я смог извлечь с помощью getMovies(), который вернет список фильмов.

Когда я запускаю, я просто получаю null object reference, потому что response имеет значение null. Я попытался найти учебники по использованию нового Retrofit-2.0.0, особенно при использовании функции enqueue, но мне не повезло. Плюс еще один вопрос, куда следует вызывать updateMovies(). Могу ли я вызвать его непосредственно в mainactivity. Модернизируется ли автоматический запуск сетевого вызова в фоновом потоке?

Ответы

Ответ 1

С Retrofit 2, onResponse вызывается, даже если есть сбой. Вы проверили, не отвечает ли ответ с помощью !response.isSuccess(). Но вы только что зарегистрировали его - если это правда (т.е. Не удалось). Вместо этого вы можете записать response.errorBody().string(), чтобы узнать, указывает ли api сервер ошибку, и вы должны вызвать что-то вроде return для выхода из обратного вызова onResponse, поскольку response.body() не может быть отправлено на MovieResponse, следовательно, значение null исключение.

Кстати, ваш код правильный, но если вы только начинаете с Retrofit, было бы проще использовать версию 1.9, так как 2.0 все еще является бета-версией (очень стабильной, хотя и отсутствием учебников).

Ответ 2

Используйте Interceptor из OkHttp On Retrofit 1.9, вы можете использовать RequestInterceptor для перехвата запроса, но он уже удален в Retrofit 2.0, так как уровень подключения HTTP был перемещен в OkHttp.

В результате мы теперь должны переключиться на Interceptor из OkHttp. Сначала вы должны добавить его в build.gradle

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

а затем создайте объект OkHttpClient с Interceptor следующим образом:

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

И затем передайте созданный клиент в цепочку Retrofit Builder.

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

Удалите '/' из вашего @GET ( "/abc" ) потому что Retrofit 2.0 поставляется с новой концепцией разрешения URL. Базовый URL-адрес и @Url не просто объединены вместе, но были решены так же, как и то, что делает. Пожалуйста, ознакомьтесь с приведенными ниже примерами для уточнения.

></a> <a href=></a> <a href=

Чтобы узнать больше о Retrofit 2.0

Ответ 3

@AbKDs, я не знаю, если вы уже решили это, но я узнал после некоторой борьбы с retrofit 2, что вам нужно поставить " http://api.themoviedb.org" как ваш baseUrl и добавьте весь путь в @GET. Например: @GET ( "/3/обнаружение/фильм" ) И затем вы добавляете свои запросы в качестве параметров для вашего вызова Call.