2015-09-07 24 views
15

我为我的应用使用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对象由包含Movie和一些额外信息的数组的movieDB API返回。我正在以这种方式实施它,以便一旦我从那里得到MovieResponse的回复,我可以使用getMovies()进行提取,这将返回一个电影列表。

当我运行时,我只是得到null object reference,因为response为空。我试图搜索关于使用新的Retrofit-2.0.0的教程,特别是使用入队函数,但我运气不佳。再加上一个问题,updateMovies()应该在哪里调用。我可以直接在主要活动中打电话吗?后期改造是否会自动在后台线程上运行网络调用?

+0

https://github.com/square/retrofit/releases/tag/parent-2.0.0-beta1 ↑这是测试版,所以我觉得你应该改为使用改进版本1.9.0(最新的稳定版本)。 –

+0

我也面临同样的问题。你有任何解决方案? – Govan

+0

类似的问题和答案:http://stackoverflow.com/questions/33202871/retrofit-error-2-0-2-beta-error-in-callback-does-not-override-abstract-method-on –

回答

14

在改造2中,onResponse即使出现故障也会被调用。您已通过使用!response.isSuccess()检查响应是否不成功。但是你只是记录了它 - 如果它是真的(即不成功)。相反,您可以记录response.errorBody().string()以查看api服务器是否指定错误,并且您应该调用类似return的退出onResponse回调,因为response.body()无法铸造到MovieResponse,因此为空例外。顺便说一句,你的代码是正确的,但如果你刚刚开始使用Retrofit,那么使用1.9版本会更简单,因为2.0仍然是一个测试版本(虽然很稳定,但缺乏教程)。

+0

使用此我找出了错误。我的帖子请求发布为GET请求。需要找到原因。不管怎样,谢谢。它有助于。 – Govan

+1

在Retrofit 2中,'response.isSuccess()'也被改为'response.isSuccessful()'。 – Marlon

0

@AbKDs,我不知道你是否已经解决了这个问题,但是经过一番改造2的努力,我发现你需要把“http://api.themoviedb.org”作为你的baseUrl,并在@GET中添加整个路径。像这样:@GET(“/ 3/discover/movie”) 然后你添加你的查询作为你的接口调用的参数。

4

使用OkHttp的拦截器在Retrofit 1.9上,您可以使用RequestInterceptor拦截请求,但由于HTTP连接层已被移动到OkHttp,所以在Retrofit 2.0上它已被删除。

因此,我们必须从现在开始切换到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 retrofit = new Retrofit.Builder().baseUrl("http://api.themoviedb.org/3/discover/").addConverterFactory(GsonConverterFactory.create()).client(client).build(); 

从@GET删除 '/'( “/ ABC”) 因为改造2.0配备了新的URL解析概念。基本URL和@Url不仅仅是简单地组合在一起,而是以与其相反的方式解决。请查看下面的示例以进行澄清。

To know more about Retrofit 2.0