在 Retrofit 中使用 Call Enqueue 函数

Using Call Enqueue function in Retrofit

我正在为我的应用程序使用 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();
        }
    });
}

不知道入队函数要实现什么。关于如何使用回调的改造网站上给出的很少。假设所有其他代码都工作正常。这里 MovieResponse 对象是由 movieDB API return 编辑的,它包含一个 Movie 数组和一些额外信息。我以这样的方式实现它,以便一旦我从那里得到 MovieResponse 中的响应,我就可以使用 getMovies() 提取,这将 return 电影列表。

当我 运行 我只是得到 null object reference 因为 response 是空的。我试图搜索有关使用 new Retrofit-2.0.0 的教程,尤其是有关使用 enqueue 函数的教程,但我运气不好。再加上一个问题 updateMovies() 应该在哪里调用。可以直接在mainactivity中调用吗?是否自动改造 运行 后台线程上的网络调用?

对于 Retrofit 2,即使出现故障也会调用 onResponse。您已使用!response.isSuccess()检查是否响应不成功。但是你只是记录了它 - 如果它是真的(即不成功)。相反,您可以记录 response.errorBody().string() 以查看 api 服务器是否指定了错误,并且您应该调用类似 return 的内容来退出 onResponse 回调,因为 response.body() 不能' 被强制转换为 MovieResponse,因此出现空异常。

顺便说一句,你的代码是正确的,但如果你只是从Retrofit开始,使用1.9版本会更简单,因为2.0仍然是测试版(虽然很稳定,但缺乏教程)。

@AbKDs,我不知道你是否已经解决了它,但在与改造 2 进行了一些斗争之后我发现你需要将“http://api.themoviedb.org”作为你的 baseUrl 并将整个路径添加到@得到。像这样:@GET("/3/discover/movie") 然后将查询添加为接口调用的参数。

使用来自 OkHttp 的拦截器在 Retrofit 1.9 上,您可以使用 RequestInterceptor 拦截请求,但它已在 Retrofit 2.0 上被删除,因为 HTTP 连接层已移至 OkHttp。

因此,我们必须从现在开始从 OkHttp 切换到拦截器。 首先,你必须将它添加到 build.gradle

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

然后创建一个带有拦截器的 OkHttpClient 对象,如下所示:

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 解析概念。 Base URL 和 @Url 不仅简单地组合在一起,而且已经以与替代方法相同的方式解决。请查看下面的示例以进行说明。

To know more about Retrofit 2.0