【问题标题】:Using Call Enqueue function in Retrofit在 Retrofit 中使用 Call Enqueue 函数
【发布时间】:2015-09-07 05:16:00
【问题描述】:

我正在为我的应用程序使用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 对象由movieDB API 返回,其中包含Movies 数组和一些额外信息。我以这样的方式实现它,这样一旦我从那里得到MovieResponse 的响应,我就可以使用getMovies() 提取它,这将返回一个电影列表。

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

【问题讨论】:

标签: android retrofit


【解决方案1】:

使用 Retrofit 2,即使出现故障,也会调用 onResponse。您已使用!response.isSuccess() 检查是否响应不成功。但是您刚刚记录了它 - 如果它是真的(即不成功)。相反,您可以记录response.errorBody().string() 以查看api 服务器是否指定错误,并且您应该调用return 之类的东西来退出onResponse 回调,因为response.body() 无法转换为MovieResponse,因此为null例外。

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

【讨论】:

  • 使用这个我发现了错误。我的 Post 请求作为 GET 请求发布。需要找出原因。不管怎样,谢谢。它有帮助。
  • response.isSuccess() 在改造 2 中也更改为 response.isSuccessful()
【解决方案2】:

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

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

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

然后用这样的 Interceptor 创建一个 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 解析概念。基本 URL 和 @Url 不仅简单地组合在一起,而且以与替代方法相同的方式进行解析。请查看以下示例以进行说明。

To know more about Retrofit 2.0

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2017-04-22
      • 1970-01-01
      • 2020-09-18
      • 1970-01-01
      • 2019-08-24
      • 2018-09-19
      • 2016-01-19
      • 2020-07-13
      • 1970-01-01
      相关资源
      最近更新 更多